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:
authorJulian Eisel <eiseljulian@gmail.com>2017-02-12 23:43:13 +0300
committerJulian Eisel <eiseljulian@gmail.com>2017-02-12 23:43:13 +0300
commit10b24eabbab0193f6944cdf3bec7b386c75d5445 (patch)
tree28cefb0f056191e09828cb79d2f7f728df4e2ead
parentf754ce1c5e050d1637fe97d78f782d6a68da6c15 (diff)
parentb104057d001d2472cc55c7fa51cff3275e331523 (diff)
Merge branch 'blender2.8' into transform-manipulators
Conflicts: source/blender/editors/interface/resources.c source/blender/editors/space_view3d/view3d_intern.h source/blender/editors/transform/transform_manipulator.c source/blender/gpu/CMakeLists.txt source/blender/gpu/intern/gpu_shader.c
-rw-r--r--CMakeLists.txt4
-rwxr-xr-xbuild_files/build_environment/install_deps.sh2
-rw-r--r--build_files/buildbot/slave_compile.py2
-rw-r--r--build_files/cmake/macros.cmake2
-rw-r--r--build_files/cmake/platform/platform_win32_msvc.cmake6
-rw-r--r--intern/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/engine.py2
-rw-r--r--intern/cycles/blender/addon/properties.py14
-rw-r--r--intern/cycles/blender/addon/ui.py10
-rw-r--r--intern/cycles/blender/blender_session.cpp3
-rw-r--r--intern/cycles/blender/blender_sync.cpp9
-rw-r--r--intern/cycles/kernel/kernel_path.h15
-rw-r--r--intern/cycles/kernel/kernel_path_common.h2
-rw-r--r--intern/cycles/kernel/kernel_types.h5
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h53
-rw-r--r--intern/cycles/render/integrator.cpp11
-rw-r--r--intern/cycles/render/integrator.h3
-rw-r--r--intern/cycles/test/render_graph_finalize_test.cpp6
-rw-r--r--intern/cycles/test/util_aligned_malloc_test.cpp2
-rw-r--r--intern/cycles/test/util_path_test.cpp100
-rw-r--r--intern/cycles/test/util_string_test.cpp64
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp60
-rw-r--r--intern/utfconv/utfconv.h2
-rw-r--r--release/datafiles/blender_icons.svg118
-rw-r--r--release/datafiles/blender_icons16/icon16_collapsemenu.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_down_bar.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_left_bar.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_right_bar.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tria_up_bar.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_collapsemenu.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_down_bar.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_left_bar.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_right_bar.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tria_up_bar.datbin4120 -> 4120 bytes
m---------release/datafiles/locale0
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py64
-rw-r--r--release/scripts/presets/keyconfig/3dsmax.py1
-rw-r--r--release/scripts/presets/keyconfig/maya.py1
-rw-r--r--release/scripts/startup/bl_operators/clip.py4
-rw-r--r--release/scripts/startup/bl_operators/freestyle.py58
-rw-r--r--release/scripts/startup/bl_operators/object.py18
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py8
-rw-r--r--release/scripts/startup/bl_ui/__init__.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_collection.py128
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py159
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py103
-rw-r--r--release/scripts/startup/bl_ui/space_collections.py41
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py8
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py95
-rw-r--r--release/scripts/templates_py/batch_export.py6
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py2
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/alembic/intern/abc_curves.cc10
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc101
-rw-r--r--source/blender/alembic/intern/abc_exporter.h9
-rw-r--r--source/blender/alembic/intern/abc_hair.cc5
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc18
-rw-r--r--source/blender/alembic/intern/abc_nurbs.cc4
-rw-r--r--source/blender/alembic/intern/abc_object.cc6
-rw-r--r--source/blender/alembic/intern/abc_util.cc41
-rw-r--r--source/blender/alembic/intern/abc_util.h12
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc16
-rw-r--r--source/blender/blenfont/BLF_api.h28
-rw-r--r--source/blender/blenfont/intern/blf.c145
-rw-r--r--source/blender/blenfont/intern/blf_font.c10
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h6
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h1
-rw-r--r--source/blender/blenkernel/BKE_collection.h91
-rw-r--r--source/blender/blenkernel/BKE_context.h8
-rw-r--r--source/blender/blenkernel/BKE_group.h5
-rw-r--r--source/blender/blenkernel/BKE_layer.h221
-rw-r--r--source/blender/blenkernel/BKE_library.h5
-rw-r--r--source/blender/blenkernel/BKE_library_query.h29
-rw-r--r--source/blender/blenkernel/BKE_main.h23
-rw-r--r--source/blender/blenkernel/BKE_modifier.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h7
-rw-r--r--source/blender/blenkernel/BKE_object.h14
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h2
-rw-r--r--source/blender/blenkernel/BKE_sca.h6
-rw-r--r--source/blender/blenkernel/BKE_scene.h26
-rw-r--r--source/blender/blenkernel/BKE_texture.h7
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c15
-rw-r--r--source/blender/blenkernel/intern/anim.c4
-rw-r--r--source/blender/blenkernel/intern/armature.c14
-rw-r--r--source/blender/blenkernel/intern/blender.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c2
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c237
-rw-r--r--source/blender/blenkernel/intern/cachefile.c10
-rw-r--r--source/blender/blenkernel/intern/camera.c2
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c44
-rw-r--r--source/blender/blenkernel/intern/collection.c453
-rw-r--r--source/blender/blenkernel/intern/collision.c4
-rw-r--r--source/blender/blenkernel/intern/context.c67
-rw-r--r--source/blender/blenkernel/intern/customdata.c2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c4
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/group.c17
-rw-r--r--source/blender/blenkernel/intern/lamp.c8
-rw-r--r--source/blender/blenkernel/intern/layer.c1096
-rw-r--r--source/blender/blenkernel/intern/library.c252
-rw-r--r--source/blender/blenkernel/intern/library_query.c365
-rw-r--r--source/blender/blenkernel/intern/library_remap.c95
-rw-r--r--source/blender/blenkernel/intern/material.c11
-rw-r--r--source/blender/blenkernel/intern/mball.c32
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_render.c2
-rw-r--r--source/blender/blenkernel/intern/node.c17
-rw-r--r--source/blender/blenkernel/intern/object.c98
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c2
-rw-r--r--source/blender/blenkernel/intern/particle.c5
-rw-r--r--source/blender/blenkernel/intern/particle_system.c12
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c8
-rw-r--r--source/blender/blenkernel/intern/sca.c44
-rw-r--r--source/blender/blenkernel/intern/scene.c257
-rw-r--r--source/blender/blenkernel/intern/sequencer.c89
-rw-r--r--source/blender/blenkernel/intern/smoke.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c6
-rw-r--r--source/blender/blenkernel/intern/sound.c6
-rw-r--r--source/blender/blenkernel/intern/text.c16
-rw-r--r--source/blender/blenkernel/intern/texture.c15
-rw-r--r--source/blender/blenlib/BLI_dynlib.h2
-rw-r--r--source/blender/blenlib/BLI_ghash.h1
-rw-r--r--source/blender/blenlib/BLI_iterator.h54
-rw-r--r--source/blender/blenlib/BLI_math_geom.h4
-rw-r--r--source/blender/blenlib/BLI_sys_types.h5
-rw-r--r--source/blender/blenlib/CMakeLists.txt1
-rw-r--r--source/blender/blenlib/PIL_time_utildefines.h5
-rw-r--r--source/blender/blenlib/intern/dynlib.c4
-rw-r--r--source/blender/blenlib/intern/math_geom.c28
-rw-r--r--source/blender/blenloader/CMakeLists.txt1
-rw-r--r--source/blender/blenloader/intern/readfile.c176
-rw-r--r--source/blender/blenloader/intern/readfile.h4
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c4
-rw-r--r--source/blender/blenloader/intern/versioning_280.c187
-rw-r--r--source/blender/blenloader/intern/writefile.c454
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c4
-rw-r--r--source/blender/collada/ArmatureExporter.cpp14
-rw-r--r--source/blender/collada/DocumentImporter.cpp5
-rw-r--r--source/blender/collada/EffectExporter.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc31
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h5
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc14
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc8
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc6
-rw-r--r--source/blender/draw/CMakeLists.txt40
-rw-r--r--source/blender/draw/DRW_engine.h45
-rw-r--r--source/blender/draw/DRW_engines.h0
-rw-r--r--source/blender/draw/engines/clay/clay.c776
-rw-r--r--source/blender/draw/engines/clay/clay.h (renamed from source/blender/draw/DRW_defines.h)17
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_frag.glsl205
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_vert.glsl20
-rw-r--r--source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl73
-rw-r--r--source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl120
-rw-r--r--source/blender/draw/intern/DRW_render.h221
-rw-r--r--source/blender/draw/intern/draw_cache.c556
-rw-r--r--source/blender/draw/intern/draw_cache.h57
-rw-r--r--source/blender/draw/intern/draw_manager.c1272
-rw-r--r--source/blender/draw/intern/draw_mode_pass.c541
-rw-r--r--source/blender/draw/intern/draw_mode_pass.h45
-rw-r--r--source/blender/editors/CMakeLists.txt1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c51
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c15
-rw-r--r--source/blender/editors/animation/anim_draw.c14
-rw-r--r--source/blender/editors/animation/anim_filter.c32
-rw-r--r--source/blender/editors/animation/anim_markers.c16
-rw-r--r--source/blender/editors/animation/keyframes_draw.c234
-rw-r--r--source/blender/editors/animation/keyframes_edit.c2
-rw-r--r--source/blender/editors/armature/armature_intern.h4
-rw-r--r--source/blender/editors/armature/armature_relations.c22
-rw-r--r--source/blender/editors/armature/armature_select.c2
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c7
-rw-r--r--source/blender/editors/armature/pose_select.c2
-rw-r--r--source/blender/editors/curve/editcurve.c6
-rw-r--r--source/blender/editors/curve/editcurve_paint.c40
-rw-r--r--source/blender/editors/curve/editfont.c5
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c2
-rw-r--r--source/blender/editors/include/BIF_glutil.h24
-rw-r--r--source/blender/editors/include/ED_armature.h5
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h6
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_object.h22
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_space_api.h1
-rw-r--r--source/blender/editors/include/ED_transform.h2
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h4
-rw-r--r--source/blender/editors/include/ED_view3d.h9
-rw-r--r--source/blender/editors/include/UI_interface.h25
-rw-r--r--source/blender/editors/include/UI_interface_icons.h1
-rw-r--r--source/blender/editors/include/UI_resources.h8
-rw-r--r--source/blender/editors/interface/interface_draw.c1093
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c2
-rw-r--r--source/blender/editors/interface/interface_icons.c82
-rw-r--r--source/blender/editors/interface/interface_layout.c28
-rw-r--r--source/blender/editors/interface/interface_panel.c19
-rw-r--r--source/blender/editors/interface/interface_regions.c18
-rw-r--r--source/blender/editors/interface/interface_style.c16
-rw-r--r--source/blender/editors/interface/interface_widgets.c28
-rw-r--r--source/blender/editors/interface/resources.c73
-rw-r--r--source/blender/editors/interface/view2d.c26
-rw-r--r--source/blender/editors/interface/view2d_ops.c6
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c128
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c41
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c32
-rw-r--r--source/blender/editors/mesh/mesh_data.c2
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c7
-rw-r--r--source/blender/editors/mesh/meshtools.c446
-rw-r--r--source/blender/editors/object/object_add.c179
-rw-r--r--source/blender/editors/object/object_constraint.c11
-rw-r--r--source/blender/editors/object/object_edit.c210
-rw-r--r--source/blender/editors/object/object_group.c33
-rw-r--r--source/blender/editors/object/object_hook.c16
-rw-r--r--source/blender/editors/object/object_intern.h5
-rw-r--r--source/blender/editors/object/object_modifier.c14
-rw-r--r--source/blender/editors/object/object_ops.c25
-rw-r--r--source/blender/editors/object/object_relations.c321
-rw-r--r--source/blender/editors/object/object_select.c307
-rw-r--r--source/blender/editors/object/object_vgroup.c63
-rw-r--r--source/blender/editors/physics/physics_fluid.c4
-rw-r--r--source/blender/editors/physics/physics_pointcache.c2
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c4
-rw-r--r--source/blender/editors/physics/rigidbody_object.c4
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/render/render_preview.c2
-rw-r--r--source/blender/editors/render/render_shading.c12
-rw-r--r--source/blender/editors/screen/area.c36
-rw-r--r--source/blender/editors/screen/glutil.c186
-rw-r--r--source/blender/editors/screen/screen_context.c162
-rw-r--r--source/blender/editors/screen/screen_ops.c4
-rw-r--r--source/blender/editors/space_action/action_draw.c53
-rw-r--r--source/blender/editors/space_api/spacetypes.c1
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c38
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c261
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c140
-rw-r--r--source/blender/editors/space_clip/clip_utils.c52
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c20
-rw-r--r--source/blender/editors/space_collections/CMakeLists.txt45
-rw-r--r--source/blender/editors/space_collections/collections_intern.h35
-rw-r--r--source/blender/editors/space_collections/collections_ops.c340
-rw-r--r--source/blender/editors/space_collections/space_collections.c182
-rw-r--r--source/blender/editors/space_file/file_draw.c22
-rw-r--r--source/blender/editors/space_graph/space_graph.c75
-rw-r--r--source/blender/editors/space_info/info_stats.c16
-rw-r--r--source/blender/editors/space_info/textview.c7
-rw-r--r--source/blender/editors/space_logic/logic_window.c4
-rw-r--r--source/blender/editors/space_nla/nla_channels.c15
-rw-r--r--source/blender/editors/space_nla/nla_draw.c382
-rw-r--r--source/blender/editors/space_node/drawnode.c22
-rw-r--r--source/blender/editors/space_node/node_draw.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c442
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c209
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h11
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c9
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c149
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c94
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c98
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c11
-rw-r--r--source/blender/editors/space_time/space_time.c2
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c125
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c255
-rw-r--r--source/blender/editors/space_view3d/drawobject.c102
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c118
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c70
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c135
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h12
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c223
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c124
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c30
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c2
-rw-r--r--source/blender/editors/transform/transform.c39
-rw-r--r--source/blender/editors/transform/transform.h5
-rw-r--r--source/blender/editors/transform/transform_constraints.c34
-rw-r--r--source/blender/editors/transform/transform_conversions.c89
-rw-r--r--source/blender/editors/transform/transform_generics.c49
-rw-r--r--source/blender/editors/transform/transform_orientations.c14
-rw-r--r--source/blender/editors/transform/transform_snap.c66
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1793
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c415
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp8
-rw-r--r--source/blender/gpu/CMakeLists.txt15
-rw-r--r--source/blender/gpu/GPU_batch.h6
-rw-r--r--source/blender/gpu/GPU_extensions.h2
-rw-r--r--source/blender/gpu/GPU_framebuffer.h1
-rw-r--r--source/blender/gpu/GPU_matrix.h3
-rw-r--r--source/blender/gpu/GPU_shader.h15
-rw-r--r--source/blender/gpu/GPU_texture.h116
-rw-r--r--source/blender/gpu/GPU_uniformbuffer.h44
-rw-r--r--source/blender/gpu/GPU_viewport.h47
-rw-r--r--source/blender/gpu/gawain/batch.c99
-rw-r--r--source/blender/gpu/gawain/batch.h7
-rw-r--r--source/blender/gpu/gawain/buffer_id.cpp5
-rw-r--r--source/blender/gpu/gawain/immediate.c58
-rw-r--r--source/blender/gpu/gawain/immediate.h4
-rw-r--r--source/blender/gpu/gawain/vertex_buffer.c2
-rw-r--r--source/blender/gpu/intern/gpu_batch.c87
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c2
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c112
-rw-r--r--source/blender/gpu/intern/gpu_draw.c65
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c15
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c42
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c5
-rw-r--r--source/blender/gpu/intern/gpu_material.c13
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c32
-rw-r--r--source/blender/gpu/intern/gpu_shader.c69
-rw-r--r--source/blender/gpu/intern/gpu_texture.c613
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c105
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c227
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_checker_frag.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl38
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl44
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl16
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h12
-rw-r--r--source/blender/imbuf/intern/colormanagement.c173
-rw-r--r--source/blender/makesdna/DNA_layer_types.h160
-rw-r--r--source/blender/makesdna/DNA_material_types.h40
-rw-r--r--source/blender/makesdna/DNA_object_types.h8
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h1
-rw-r--r--source/blender/makesdna/DNA_scene_types.h97
-rw-r--r--source/blender/makesdna/DNA_space_types.h53
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/RNA_access.h10
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt5
-rw-r--r--source/blender/makesrna/intern/rna_context.c35
-rw-r--r--source/blender/makesrna/intern/rna_group.c12
-rw-r--r--source/blender/makesrna/intern/rna_internal.h2
-rw-r--r--source/blender/makesrna/intern/rna_material.c143
-rw-r--r--source/blender/makesrna/intern/rna_object.c42
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c73
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c2
-rw-r--r--source/blender/makesrna/intern/rna_render.c30
-rw-r--r--source/blender/makesrna/intern/rna_scene.c1284
-rw-r--r--source/blender/makesrna/intern/rna_space.c19
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c30
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c2
-rw-r--r--source/blender/modifiers/intern/MOD_array.c8
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c2
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c2
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c4
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c2
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c11
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c213
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c8
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c4
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c2
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c2
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c2
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c4
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c10
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c4
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c4
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c8
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c6
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c1
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c2
-rw-r--r--source/blender/python/intern/gpu.c1
-rw-r--r--source/blender/render/CMakeLists.txt1
-rw-r--r--source/blender/render/extern/include/RE_engine.h6
-rw-r--r--source/blender/render/intern/source/convertblender.c2
-rw-r--r--source/blender/render/intern/source/envmap.c2
-rw-r--r--source/blender/render/intern/source/external_engine.c24
-rw-r--r--source/blender/render/intern/source/pipeline.c2
-rw-r--r--source/blender/render/intern/source/voxeldata.c1
-rw-r--r--source/blender/windowmanager/WM_types.h1
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c4
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c4
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c8
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c45
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Light.h4
m---------source/tools0
-rw-r--r--tests/gtests/blenlib/BLI_array_store_test.cc40
-rw-r--r--tests/gtests/blenlib/BLI_array_utils_test.cc36
-rw-r--r--tests/gtests/blenlib/BLI_ghash_performance_test.cc18
-rw-r--r--tests/gtests/blenlib/BLI_ghash_test.cc34
-rw-r--r--tests/gtests/blenlib/BLI_hash_mm2a_test.cc16
-rw-r--r--tests/gtests/blenlib/BLI_listbase_test.cc26
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc16
-rw-r--r--tests/gtests/blenlib/BLI_polyfill2d_test.cc10
-rw-r--r--tests/gtests/blenlib/BLI_stack_test.cc32
-rw-r--r--tests/gtests/blenlib/BLI_string_test.cc102
-rw-r--r--tests/gtests/blenlib/BLI_string_utf8_test.cc2
-rw-r--r--tests/gtests/bmesh/bmesh_core_test.cc18
-rw-r--r--tests/gtests/guardedalloc/guardedalloc_alignment_test.cc2
-rw-r--r--tests/python/CMakeLists.txt7
-rw-r--r--tests/python/bl_render_layer.py1040
-rwxr-xr-xtests/python/cycles_render_tests.py1
422 files changed, 19672 insertions, 7571 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index de01be1d299..a107dd78fbb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -242,6 +242,8 @@ endif()
option(WITH_PLAYER "Build Player" OFF)
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
+option(WITH_CLAY_ENGINE "Enable New Clay engine (Breaks Mac and Intel compatibility)" ON)
+
# Compositor
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
@@ -722,7 +724,7 @@ if(NOT WITH_BOOST)
macro(set_and_warn
_setting _val)
if(${${_setting}})
- message(STATUS "'WITH_BOOST' is disabled: forceing 'set(${_setting} ${_val})'")
+ message(STATUS "'WITH_BOOST' is disabled: forcing 'set(${_setting} ${_val})'")
endif()
set(${_setting} ${_val})
endmacro()
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index a8519f54d0a..c167d392100 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -787,7 +787,7 @@ CXXFLAGS_BACK=$CXXFLAGS
if [ "$USE_CXX11" = true ]; then
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.
+ * 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.
Please note that until the transition to C++11-built libraries if completed in your distribution, situation will
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index 76d538ad578..860dd1174cf 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -72,10 +72,8 @@ if 'cmake' in builder:
# Set up OSX architecture
if builder.endswith('x86_64_10_6_cmake'):
cmake_extra_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64')
- cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda8-hack/bin/nvcc')
cmake_extra_options.append('-DWITH_CODEC_QUICKTIME=OFF')
cmake_extra_options.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=10.6')
- build_cubins = False
elif builder.startswith('win'):
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 09428953a46..fa9c2a28cb5 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -566,6 +566,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_editor_space_userpref
bf_editor_space_view3d
bf_editor_space_clip
+ bf_editor_space_collections
bf_editor_transform
bf_editor_util
@@ -597,6 +598,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_modifiers
bf_bmesh
bf_gpu
+ bf_draw
bf_blenloader
bf_blenkernel
bf_physics
diff --git a/build_files/cmake/platform/platform_win32_msvc.cmake b/build_files/cmake/platform/platform_win32_msvc.cmake
index 1a266df7791..45a44596e61 100644
--- a/build_files/cmake/platform/platform_win32_msvc.cmake
+++ b/build_files/cmake/platform/platform_win32_msvc.cmake
@@ -453,6 +453,12 @@ if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
)
+ set(OPENSUBDIV_HAS_OPENMP TRUE)
+ set(OPENSUBDIV_HAS_TBB FALSE)
+ set(OPENSUBDIV_HAS_OPENCL TRUE)
+ set(OPENSUBDIV_HAS_CUDA FALSE)
+ set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
+ set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
windows_find_package(OpenSubdiv)
endif()
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 9a5476772ab..dd9889c81ba 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -62,7 +62,7 @@ if(WITH_IK_ITASC)
add_subdirectory(itasc)
endif()
-if(WITH_IK_SOLVER OR WITH_GAMEENGINE OR WITH_MOD_BOOLEAN)
+if(WITH_GAMEENGINE)
add_subdirectory(moto)
endif()
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 2c5365c9189..c8c9ef58c52 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -62,7 +62,7 @@ def _parse_command_line():
num_resumable_chunks = None
current_resumable_chunk = None
- # TODO(sergey): Add some nice error ptins if argument is not used properly.
+ # TODO(sergey): Add some nice error prints if argument is not used properly.
idx = 0
while idx < len(argv) - 1:
arg = argv[idx]
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 802b9b76c5d..5c51f9afc28 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -638,6 +638,20 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
items=enum_texture_limit
)
+ cls.ao_bounces = IntProperty(
+ name="AO Bounces",
+ default=0,
+ description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
+ min=0, max=1024,
+ )
+
+ cls.ao_bounces_render = IntProperty(
+ name="AO Bounces Render",
+ default=0,
+ description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
+ min=0, max=1024,
+ )
+
# Various fine-tuning debug flags
def devices_update_callback(self, context):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index a1e78623d29..eb89f0b1efa 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1038,10 +1038,11 @@ class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
layout = self.layout
light = context.world.light_settings
+ scene = context.scene
row = layout.row()
sub = row.row()
- sub.active = light.use_ambient_occlusion
+ sub.active = light.use_ambient_occlusion or scene.render.use_simplify
sub.prop(light, "ao_factor", text="Factor")
row.prop(light, "distance", text="Distance")
@@ -1613,6 +1614,13 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
row.active = cscene.use_distance_cull
row.prop(cscene, "distance_cull_margin", text="Distance")
+ split = layout.split()
+ col = split.column()
+ col.prop(cscene, "ao_bounces")
+
+ col = split.column()
+ col.prop(cscene, "ao_bounces_render")
+
def draw_device(self, context):
scene = context.scene
layout = self.layout
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 04b5c3fa013..2f30cbd961f 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -1352,6 +1352,9 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
VLOG(1) << "Samples range start is " << range_start_sample << ", "
<< "number of samples to render is " << range_num_samples;
+ scene->integrator->start_sample = range_start_sample;
+ scene->integrator->tag_update(scene);
+
session->tile_manager.range_start_sample = range_start_sample;
session->tile_manager.range_num_samples = range_num_samples;
}
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index f8f2303ec76..d8043105cd8 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -322,6 +322,15 @@ void BlenderSync::sync_integrator()
integrator->volume_samples = volume_samples;
}
+ if(b_scene.render().use_simplify()) {
+ if(preview) {
+ integrator->ao_bounces = get_int(cscene, "ao_bounces");
+ }
+ else {
+ integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
+ }
+ }
+
if(integrator->modified(previntegrator))
integrator->tag_update(scene);
}
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 8ce9a4f02ec..f90701a8260 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -109,6 +109,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* intersect scene */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, state);
+ if(state->bounce > kernel_data.integrator.ao_bounces) {
+ visibility = PATH_RAY_SHADOW;
+ ray->t = kernel_data.background.ao_distance;
+ }
bool hit = scene_intersect(kg,
*ray,
visibility,
@@ -292,6 +296,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
break;
}
+ else if(state->bounce > kernel_data.integrator.ao_bounces) {
+ break;
+ }
/* setup shading */
shader_setup_from_ray(kg,
@@ -627,6 +634,11 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
}
+ if(state.bounce > kernel_data.integrator.ao_bounces) {
+ visibility = PATH_RAY_SHADOW;
+ ray.t = kernel_data.background.ao_distance;
+ }
+
bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
#else
bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f);
@@ -769,6 +781,9 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
break;
}
+ else if(state.bounce > kernel_data.integrator.ao_bounces) {
+ break;
+ }
/* setup shading */
shader_setup_from_ray(kg, &sd, &isect, &ray);
diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h
index 13597eab287..7b903556bf9 100644
--- a/intern/cycles/kernel/kernel_path_common.h
+++ b/intern/cycles/kernel/kernel_path_common.h
@@ -30,7 +30,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
int num_samples = kernel_data.integrator.aa_samples;
- if(sample == 0) {
+ if(sample == kernel_data.integrator.start_sample) {
*rng_state = hash_int_2d(x, y);
}
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index b7af90cd739..8c271c75e44 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -1143,6 +1143,8 @@ typedef struct KernelIntegrator {
int max_transmission_bounce;
int max_volume_bounce;
+ int ao_bounces;
+
/* transparent */
int transparent_min_bounce;
int transparent_max_bounce;
@@ -1186,7 +1188,8 @@ typedef struct KernelIntegrator {
float light_inv_rr_threshold;
- int pad1;
+ int start_sample;
+ int pad1, pad2, pad3;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index 01547b60014..a7f15de7325 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -134,32 +134,37 @@ ccl_device float3 svm_math_blackbody_color(float t) {
{ 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f },
};
- if(t >= 12000.0f)
+ int i;
+ if(t >= 12000.0f) {
return make_float3(0.826270103f, 0.994478524f, 1.56626022f);
+ }
+ else if(t >= 6365.0f) {
+ i = 5;
+ }
+ else if(t >= 3315.0f) {
+ i = 4;
+ }
+ else if(t >= 1902.0f) {
+ i = 3;
+ }
+ else if(t >= 1449.0f) {
+ i = 2;
+ }
+ else if(t >= 1167.0f) {
+ i = 1;
+ }
+ else if(t >= 965.0f) {
+ i = 0;
+ }
+ else {
+ /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
+ return make_float3(4.70366907f, 0.0f, 0.0f);
+ }
- /* Define a macro to reduce stack usage for nvcc */
-#define MAKE_BB_RGB(i) make_float3(\
- rc[i][0] / t + rc[i][1] * t + rc[i][2],\
- gc[i][0] / t + gc[i][1] * t + gc[i][2],\
- ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3])
-
- if(t >= 6365.0f)
- return MAKE_BB_RGB(5);
- if(t >= 3315.0f)
- return MAKE_BB_RGB(4);
- if(t >= 1902.0f)
- return MAKE_BB_RGB(3);
- if(t >= 1449.0f)
- return MAKE_BB_RGB(2);
- if(t >= 1167.0f)
- return MAKE_BB_RGB(1);
- if(t >= 965.0f)
- return MAKE_BB_RGB(0);
-
-#undef MAKE_BB_RGB
-
- /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
- return make_float3(4.70366907f, 0.0f, 0.0f);
+ const float t_inv = 1.0f / t;
+ return make_float3(rc[i][0] * t_inv + rc[i][1] * t + rc[i][2],
+ gc[i][0] * t_inv + gc[i][1] * t + gc[i][2],
+ ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3]);
}
ccl_device_inline float3 svm_math_gamma_color(float3 color, float gamma)
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index a9a33d2e789..1ab0f9874f2 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -43,6 +43,8 @@ NODE_DEFINE(Integrator)
SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7);
SOCKET_BOOLEAN(transparent_shadows, "Transparent Shadows", false);
+ SOCKET_INT(ao_bounces, "AO Bounces", 0);
+
SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024);
SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f);
@@ -62,6 +64,7 @@ NODE_DEFINE(Integrator)
SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1);
SOCKET_INT(subsurface_samples, "Subsurface Samples", 1);
SOCKET_INT(volume_samples, "Volume Samples", 1);
+ SOCKET_INT(start_sample, "Start Sample", 0);
SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true);
SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true);
@@ -111,6 +114,13 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
kintegrator->transparent_min_bounce = transparent_min_bounce + 1;
+ if(ao_bounces == 0) {
+ kintegrator->ao_bounces = INT_MAX;
+ }
+ else {
+ kintegrator->ao_bounces = ao_bounces - 1;
+ }
+
/* Transparent Shadows
* We only need to enable transparent shadows, if we actually have
* transparent shaders in the scene. Otherwise we can disable it
@@ -152,6 +162,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->mesh_light_samples = mesh_light_samples;
kintegrator->subsurface_samples = subsurface_samples;
kintegrator->volume_samples = volume_samples;
+ kintegrator->start_sample = start_sample;
if(method == BRANCHED_PATH) {
kintegrator->sample_all_lights_direct = sample_all_lights_direct;
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 17fdd0ef1db..27fff4831e5 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -43,6 +43,8 @@ public:
int transparent_max_bounce;
bool transparent_shadows;
+ int ao_bounces;
+
int volume_max_steps;
float volume_step_size;
@@ -64,6 +66,7 @@ public:
int mesh_light_samples;
int subsurface_samples;
int volume_samples;
+ int start_sample;
bool sample_all_lights_direct;
bool sample_all_lights_indirect;
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
index 32b4c7265ee..3fc086cbc0c 100644
--- a/intern/cycles/test/render_graph_finalize_test.cpp
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -92,7 +92,7 @@ public:
template<typename T>
ShaderGraphBuilder& add_node(const T& node)
{
- EXPECT_EQ(NULL, find_node(node.name()));
+ EXPECT_EQ(find_node(node.name()), (void*)NULL);
graph_->add(node.node());
node_map_[node.name()] = node.node();
return *this;
@@ -104,8 +104,8 @@ public:
vector<string> tokens_from, tokens_to;
string_split(tokens_from, from, "::");
string_split(tokens_to, to, "::");
- EXPECT_EQ(2, tokens_from.size());
- EXPECT_EQ(2, tokens_to.size());
+ EXPECT_EQ(tokens_from.size(), 2);
+ EXPECT_EQ(tokens_to.size(), 2);
ShaderNode *node_from = find_node(tokens_from[0]),
*node_to = find_node(tokens_to[0]);
EXPECT_NE((void*)NULL, node_from);
diff --git a/intern/cycles/test/util_aligned_malloc_test.cpp b/intern/cycles/test/util_aligned_malloc_test.cpp
index 479070f0513..9fb3aad0c3f 100644
--- a/intern/cycles/test/util_aligned_malloc_test.cpp
+++ b/intern/cycles/test/util_aligned_malloc_test.cpp
@@ -18,7 +18,7 @@
#include "util/util_aligned_malloc.h"
-#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ(0, (size_t)ptr % align)
+#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ((size_t)ptr % align, 0)
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/test/util_path_test.cpp b/intern/cycles/test/util_path_test.cpp
index 92be1dd4cbe..c2f400c105d 100644
--- a/intern/cycles/test/util_path_test.cpp
+++ b/intern/cycles/test/util_path_test.cpp
@@ -26,63 +26,63 @@ CCL_NAMESPACE_BEGIN
TEST(util_path_filename, simple_unix)
{
string str = path_filename("/tmp/foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, root_unix)
{
string str = path_filename("/");
- EXPECT_EQ("/", str);
+ EXPECT_EQ(str, "/");
}
TEST(util_path_filename, last_slash_unix)
{
string str = path_filename("/tmp/foo.txt/");
- EXPECT_EQ(".", str);
+ EXPECT_EQ(str, ".");
}
TEST(util_path_filename, alternate_slash_unix)
{
string str = path_filename("/tmp\\foo.txt");
- EXPECT_EQ("tmp\\foo.txt", str);
+ EXPECT_EQ(str, "tmp\\foo.txt");
}
#endif /* !_WIN32 */
TEST(util_path_filename, file_only)
{
string str = path_filename("foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, empty)
{
string str = path_filename("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
#ifdef _WIN32
TEST(util_path_filename, simple_windows)
{
string str = path_filename("C:\\tmp\\foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, root_windows)
{
string str = path_filename("C:\\");
- EXPECT_EQ("\\", str);
+ EXPECT_EQ(str, "\\");
}
TEST(util_path_filename, last_slash_windows)
{
string str = path_filename("C:\\tmp\\foo.txt\\");
- EXPECT_EQ(".", str);
+ EXPECT_EQ(str, ".");
}
TEST(util_path_filename, alternate_slash_windows)
{
string str = path_filename("C:\\tmp/foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
#endif /* _WIN32 */
@@ -92,63 +92,63 @@ TEST(util_path_filename, alternate_slash_windows)
TEST(util_path_dirname, simple_unix)
{
string str = path_dirname("/tmp/foo.txt");
- EXPECT_EQ("/tmp", str);
+ EXPECT_EQ(str, "/tmp");
}
TEST(util_path_dirname, root_unix)
{
string str = path_dirname("/");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_path_dirname, last_slash_unix)
{
string str = path_dirname("/tmp/foo.txt/");
- EXPECT_EQ("/tmp/foo.txt", str);
+ EXPECT_EQ(str, "/tmp/foo.txt");
}
TEST(util_path_dirname, alternate_slash_unix)
{
string str = path_dirname("/tmp\\foo.txt");
- EXPECT_EQ("/", str);
+ EXPECT_EQ(str, "/");
}
#endif /* !_WIN32 */
TEST(util_path_dirname, file_only)
{
string str = path_dirname("foo.txt");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_path_dirname, empty)
{
string str = path_dirname("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
#ifdef _WIN32
TEST(util_path_dirname, simple_windows)
{
string str = path_dirname("C:\\tmp\\foo.txt");
- EXPECT_EQ("C:\\tmp", str);
+ EXPECT_EQ(str, "C:\\tmp");
}
TEST(util_path_dirname, root_windows)
{
string str = path_dirname("C:\\");
- EXPECT_EQ("C:", str);
+ EXPECT_EQ(str, "C:");
}
TEST(util_path_dirname, last_slash_windows)
{
string str = path_dirname("C:\\tmp\\foo.txt\\");
- EXPECT_EQ("C:\\tmp\\foo.txt", str);
+ EXPECT_EQ(str, "C:\\tmp\\foo.txt");
}
TEST(util_path_dirname, alternate_slash_windows)
{
string str = path_dirname("C:\\tmp/foo.txt");
- EXPECT_EQ("C:\\tmp", str);
+ EXPECT_EQ(str, "C:\\tmp");
}
#endif /* _WIN32 */
@@ -157,152 +157,152 @@ TEST(util_path_dirname, alternate_slash_windows)
TEST(util_path_join, empty_both)
{
string str = path_join("", "");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_path_join, empty_directory)
{
string str = path_join("", "foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_join, empty_filename)
{
string str = path_join("foo", "");
- EXPECT_EQ("foo", str);
+ EXPECT_EQ(str, "foo");
}
#ifndef _WIN32
TEST(util_path_join, simple_unix)
{
string str = path_join("foo", "bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, directory_slash_unix)
{
string str = path_join("foo/", "bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, filename_slash_unix)
{
string str = path_join("foo", "/bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, both_slash_unix)
{
string str = path_join("foo/", "/bar");
- EXPECT_EQ("foo//bar", str);
+ EXPECT_EQ(str, "foo//bar");
}
TEST(util_path_join, directory_alternate_slash_unix)
{
string str = path_join("foo\\", "bar");
- EXPECT_EQ("foo\\/bar", str);
+ EXPECT_EQ(str, "foo\\/bar");
}
TEST(util_path_join, filename_alternate_slash_unix)
{
string str = path_join("foo", "\\bar");
- EXPECT_EQ("foo/\\bar", str);
+ EXPECT_EQ(str, "foo/\\bar");
}
TEST(util_path_join, both_alternate_slash_unix)
{
string str = path_join("foo", "\\bar");
- EXPECT_EQ("foo/\\bar", str);
+ EXPECT_EQ(str, "foo/\\bar");
}
TEST(util_path_join, empty_dir_filename_slash_unix)
{
string str = path_join("", "/foo.txt");
- EXPECT_EQ("/foo.txt", str);
+ EXPECT_EQ(str, "/foo.txt");
}
TEST(util_path_join, empty_dir_filename_alternate_slash_unix)
{
string str = path_join("", "\\foo.txt");
- EXPECT_EQ("\\foo.txt", str);
+ EXPECT_EQ(str, "\\foo.txt");
}
TEST(util_path_join, empty_filename_dir_slash_unix)
{
string str = path_join("foo/", "");
- EXPECT_EQ("foo/", str);
+ EXPECT_EQ(str, "foo/");
}
TEST(util_path_join, empty_filename_dir_alternate_slash_unix)
{
string str = path_join("foo\\", "");
- EXPECT_EQ("foo\\", str);
+ EXPECT_EQ(str, "foo\\");
}
#else /* !_WIN32 */
TEST(util_path_join, simple_windows)
{
string str = path_join("foo", "bar");
- EXPECT_EQ("foo\\bar", str);
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, directory_slash_windows)
{
string str = path_join("foo\\", "bar");
- EXPECT_EQ("foo\\bar", str);
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, filename_slash_windows)
{
string str = path_join("foo", "\\bar");
- EXPECT_EQ("foo\\bar", str);
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, both_slash_windows)
{
string str = path_join("foo\\", "\\bar");
- EXPECT_EQ("foo\\\\bar", str);
+ EXPECT_EQ(str, "foo\\\\bar");
}
TEST(util_path_join, directory_alternate_slash_windows)
{
string str = path_join("foo/", "bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, filename_alternate_slash_windows)
{
string str = path_join("foo", "/bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, both_alternate_slash_windows)
{
string str = path_join("foo/", "/bar");
- EXPECT_EQ("foo//bar", str);
+ EXPECT_EQ(str, "foo//bar");
}
TEST(util_path_join, empty_dir_filename_slash_windows)
{
string str = path_join("", "\\foo.txt");
- EXPECT_EQ("\\foo.txt", str);
+ EXPECT_EQ(str, "\\foo.txt");
}
TEST(util_path_join, empty_dir_filename_alternate_slash_windows)
{
string str = path_join("", "/foo.txt");
- EXPECT_EQ("/foo.txt", str);
+ EXPECT_EQ(str, "/foo.txt");
}
TEST(util_path_join, empty_filename_dir_slash_windows)
{
string str = path_join("foo\\", "");
- EXPECT_EQ("foo\\", str);
+ EXPECT_EQ(str, "foo\\");
}
TEST(util_path_join, empty_filename_dir_alternate_slash_windows)
{
string str = path_join("foo/", "");
- EXPECT_EQ("foo/", str);
+ EXPECT_EQ(str, "foo/");
}
#endif /* !_WIN32 */
@@ -311,31 +311,31 @@ TEST(util_path_join, empty_filename_dir_alternate_slash_windows)
TEST(util_path_escape, no_escape_chars)
{
string str = path_escape("/tmp/foo/bar");
- EXPECT_EQ("/tmp/foo/bar", str);
+ EXPECT_EQ(str, "/tmp/foo/bar");
}
TEST(util_path_escape, simple)
{
string str = path_escape("/tmp/foo bar");
- EXPECT_EQ("/tmp/foo\\ bar", str);
+ EXPECT_EQ(str, "/tmp/foo\\ bar");
}
TEST(util_path_escape, simple_end)
{
string str = path_escape("/tmp/foo/bar ");
- EXPECT_EQ("/tmp/foo/bar\\ ", str);
+ EXPECT_EQ(str, "/tmp/foo/bar\\ ");
}
TEST(util_path_escape, multiple)
{
string str = path_escape("/tmp/foo bar");
- EXPECT_EQ("/tmp/foo\\ \\ bar", str);
+ EXPECT_EQ(str, "/tmp/foo\\ \\ bar");
}
TEST(util_path_escape, simple_multiple_end)
{
string str = path_escape("/tmp/foo/bar ");
- EXPECT_EQ("/tmp/foo/bar\\ \\ ", str);
+ EXPECT_EQ(str, "/tmp/foo/bar\\ \\ ");
}
/* ******** Tests for path_is_relative() ******** */
diff --git a/intern/cycles/test/util_string_test.cpp b/intern/cycles/test/util_string_test.cpp
index e502a35704b..22ec8e0ee8e 100644
--- a/intern/cycles/test/util_string_test.cpp
+++ b/intern/cycles/test/util_string_test.cpp
@@ -25,25 +25,25 @@ CCL_NAMESPACE_BEGIN
TEST(util_string_printf, no_format)
{
string str = string_printf("foo bar");
- EXPECT_EQ(str, "foo bar");
+ EXPECT_EQ("foo bar", str);
}
TEST(util_string_printf, int_number)
{
string str = string_printf("foo %d bar", 314);
- EXPECT_EQ(str, "foo 314 bar");
+ EXPECT_EQ("foo 314 bar", str);
}
TEST(util_string_printf, float_number_default_precision)
{
string str = string_printf("foo %f bar", 3.1415);
- EXPECT_EQ(str, "foo 3.141500 bar");
+ EXPECT_EQ("foo 3.141500 bar", str);
}
TEST(util_string_printf, float_number_custom_precision)
{
string str = string_printf("foo %.1f bar", 3.1415);
- EXPECT_EQ(str, "foo 3.1 bar");
+ EXPECT_EQ("foo 3.1 bar", str);
}
/* ******** Tests for string_printf() ******** */
@@ -78,44 +78,44 @@ TEST(util_string_split, empty)
{
vector<string> tokens;
string_split(tokens, "");
- EXPECT_EQ(0, tokens.size());
+ EXPECT_EQ(tokens.size(), 0);
}
TEST(util_string_split, only_spaces)
{
vector<string> tokens;
string_split(tokens, " \t\t \t");
- EXPECT_EQ(0, tokens.size());
+ EXPECT_EQ(tokens.size(), 0);
}
TEST(util_string_split, single)
{
vector<string> tokens;
string_split(tokens, "foo");
- EXPECT_EQ(1, tokens.size());
- EXPECT_EQ("foo", tokens[0]);
+ EXPECT_EQ(tokens.size(), 1);
+ EXPECT_EQ(tokens[0], "foo");
}
TEST(util_string_split, simple)
{
vector<string> tokens;
string_split(tokens, "foo a bar b");
- EXPECT_EQ(4, tokens.size());
- EXPECT_EQ("foo", tokens[0]);
- EXPECT_EQ("a", tokens[1]);
- EXPECT_EQ("bar", tokens[2]);
- EXPECT_EQ("b", tokens[3]);
+ EXPECT_EQ(tokens.size(), 4);
+ EXPECT_EQ(tokens[0], "foo");
+ EXPECT_EQ(tokens[1], "a");
+ EXPECT_EQ(tokens[2], "bar");
+ EXPECT_EQ(tokens[3], "b");
}
TEST(util_string_split, multiple_spaces)
{
vector<string> tokens;
string_split(tokens, " \t foo \ta bar b\t ");
- EXPECT_EQ(4, tokens.size());
- EXPECT_EQ("foo", tokens[0]);
- EXPECT_EQ("a", tokens[1]);
- EXPECT_EQ("bar", tokens[2]);
- EXPECT_EQ("b", tokens[3]);
+ EXPECT_EQ(tokens.size(), 4);
+ EXPECT_EQ(tokens[0], "foo");
+ EXPECT_EQ(tokens[1], "a");
+ EXPECT_EQ(tokens[2], "bar");
+ EXPECT_EQ(tokens[3], "b");
}
/* ******** Tests for string_replace() ******** */
@@ -124,35 +124,35 @@ TEST(util_string_replace, empty_haystack_and_other)
{
string str = "";
string_replace(str, "x", "");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, empty_haystack)
{
string str = "";
string_replace(str, "x", "y");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, empty_other)
{
string str = "x";
string_replace(str, "x", "");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, long_haystack_empty_other)
{
string str = "a x b xxc";
string_replace(str, "x", "");
- EXPECT_EQ("a b c", str);
+ EXPECT_EQ(str, "a b c");
}
TEST(util_string_replace, long_haystack)
{
string str = "a x b xxc";
string_replace(str, "x", "FOO");
- EXPECT_EQ("a FOO b FOOFOOc", str);
+ EXPECT_EQ(str, "a FOO b FOOFOOc");
}
/* ******** Tests for string_endswith() ******** */
@@ -192,25 +192,25 @@ TEST(util_string_endswith, simple_false)
TEST(util_string_strip, empty)
{
string str = string_strip("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_strip, only_spaces)
{
string str = string_strip(" ");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_strip, no_spaces)
{
string str = string_strip("foo bar");
- EXPECT_EQ("foo bar", str);
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_strip, with_spaces)
{
string str = string_strip(" foo bar ");
- EXPECT_EQ("foo bar", str);
+ EXPECT_EQ(str, "foo bar");
}
/* ******** Tests for string_remove_trademark() ******** */
@@ -218,31 +218,31 @@ TEST(util_string_strip, with_spaces)
TEST(util_string_remove_trademark, empty)
{
string str = string_remove_trademark("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_remove_trademark, no_trademark)
{
string str = string_remove_trademark("foo bar");
- EXPECT_EQ("foo bar", str);
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_remove_trademark, only_tm)
{
string str = string_remove_trademark("foo bar(TM) zzz");
- EXPECT_EQ("foo bar zzz", str);
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, only_r)
{
string str = string_remove_trademark("foo bar(R) zzz");
- EXPECT_EQ("foo bar zzz", str);
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, both)
{
string str = string_remove_trademark("foo bar(TM)(R) zzz");
- EXPECT_EQ("foo bar zzz", str);
+ EXPECT_EQ(str, "foo bar zzz");
}
CCL_NAMESPACE_END
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 992200a0b09..8cee785cdf6 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -1316,10 +1316,12 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
if (type == GHOST_kDrawingContextTypeOpenGL) {
// During development:
+ // try 4.x compatibility profile
// try 3.3 compatibility profile
// fall back to 3.0 if needed
//
// Final Blender 2.8:
+ // try 4.x core profile
// try 3.3 core profile
// no fallbacks
@@ -1332,24 +1334,9 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
# error // must specify either core or compat at build time
#endif
- GHOST_Context *context = new GHOST_ContextGLX(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_display,
- m_visualInfo,
- (GLXFBConfig)m_fbconfig,
- 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);
+ GHOST_Context *context;
- if (context->initializeDrawingContext())
- return context;
- else {
- delete context;
-
- // since that failed try 3.0 (mostly for Mesa, which doesn't implement compatibility profile)
+ for (int minor = 5; minor >= 0; --minor) {
context = new GHOST_ContextGLX(
m_wantStereoVisual,
m_wantNumOfAASamples,
@@ -1357,8 +1344,8 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
m_display,
m_visualInfo,
(GLXFBConfig)m_fbconfig,
- 0, // no profile bit
- 3, 0,
+ profile_mask,
+ 4, minor,
GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
@@ -1367,6 +1354,41 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
else
delete context;
}
+
+ context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ (GLXFBConfig)m_fbconfig,
+ 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);
+
+ if (context->initializeDrawingContext())
+ return context;
+ 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/intern/utfconv/utfconv.h b/intern/utfconv/utfconv.h
index f00f4aeef27..d05ed61c8d8 100644
--- a/intern/utfconv/utfconv.h
+++ b/intern/utfconv/utfconv.h
@@ -93,7 +93,7 @@ wchar_t *alloc_utf16_from_8(const char *in8, size_t add);
/* Easy allocation and conversion of new utf-16 string. New string has _16 suffix. Must be deallocated with UTF16_UN_ENCODE in right order*/
#define UTF16_ENCODE(in8str) if (1) { \
- wchar_t *in8str ## _16 = alloc_utf16_from_8((char *)in8str, 0)
+ wchar_t *in8str ## _16 = alloc_utf16_from_8((const char *)in8str, 0)
#define UTF16_UN_ENCODE(in8str) \
free(in8str ## _16); } (void)0
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index b54cadd40bc..e9c114ba1bd 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -14,7 +14,7 @@
height="640"
id="svg2"
sodipodi:version="0.32"
- inkscape:version="0.91 r13725"
+ inkscape:version="0.91 r"
version="1.0"
sodipodi:docname="blender_icons.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
@@ -28201,7 +28201,7 @@
xlink:href="#linearGradient37542-29"
id="linearGradient17610"
gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ gradientTransform="matrix(-1,0,0,1,865.01833,131.0342)"
x1="392.0101"
y1="224.99998"
x2="392.0101"
@@ -28263,7 +28263,7 @@
xlink:href="#linearGradient37542-29-7"
id="linearGradient17610-0"
gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(-1,0,0,1,461.01011,-167)"
+ gradientTransform="translate(128.00098,130.98191)"
x1="392.0101"
y1="224.99998"
x2="392.0101"
@@ -28402,7 +28402,7 @@
x2="228.5468"
y1="118.91647"
x1="228.5468"
- gradientTransform="matrix(1.180548,0,0,0.90042534,265.27784,265.13062)"
+ gradientTransform="matrix(1.180548,0,0,0.90042534,265.83288,265.61628)"
gradientUnits="userSpaceOnUse"
id="linearGradient17838"
xlink:href="#linearGradient319-36-40-2"
@@ -28433,7 +28433,7 @@
x2="228.5468"
y1="118.91647"
x1="228.5468"
- gradientTransform="matrix(1.180548,0,0,0.90042534,223.26222,270.47438)"
+ gradientTransform="matrix(1.180548,0,0,0.90042534,223.81726,270.99473)"
gradientUnits="userSpaceOnUse"
id="linearGradient17872"
xlink:href="#linearGradient319-36-40-2-4"
@@ -29073,7 +29073,7 @@
xlink:href="#linearGradient27854-0-6-9"
id="linearGradient17162"
gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0,1,-1,0,782.48614,-14.46331)"
+ gradientTransform="matrix(0,1,-1,0,783.04118,-13.977664)"
x1="388.86502"
y1="244.02"
x2="391.43173"
@@ -29083,7 +29083,7 @@
xlink:href="#linearGradient37542-29-7-8"
id="linearGradient17165"
gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0,1,-1,0,782.48614,-14.46331)"
+ gradientTransform="matrix(0,1,-1,0,783.04118,-13.977664)"
x1="368.97806"
y1="249.99998"
x2="393.85385"
@@ -29113,7 +29113,7 @@
xlink:href="#linearGradient37542-29-1"
id="linearGradient17185"
gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0,-1,-1,0,740.48614,764.46331)"
+ gradientTransform="matrix(0,-1,-1,0,741.04118,764.98366)"
x1="409.93588"
y1="249.99998"
x2="385.11514"
@@ -31349,17 +31349,17 @@
objecttolerance="10000"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="1.274018"
- inkscape:cx="519.70993"
- inkscape:cy="325.90484"
+ inkscape:zoom="14.413868"
+ inkscape:cx="480.24726"
+ inkscape:cy="269.95478"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
- inkscape:window-width="1920"
- inkscape:window-height="1005"
- inkscape:window-x="-2"
- inkscape:window-y="27"
- inkscape:snap-nodes="false"
+ inkscape:window-width="1680"
+ inkscape:window-height="1020"
+ inkscape:window-x="0"
+ inkscape:window-y="30"
+ inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
showguides="true"
inkscape:guide-bbox="true"
@@ -31369,14 +31369,16 @@
inkscape:snap-intersection-grid-guide="false"
inkscape:window-maximized="1"
inkscape:bbox-paths="false"
- inkscape:snap-global="false"
+ inkscape:snap-global="true"
inkscape:snap-bbox-midpoints="false"
- inkscape:snap-grids="true"
+ inkscape:snap-grids="false"
inkscape:snap-to-guides="false"
inkscape:snap-page="false"
units="pt"
inkscape:snap-center="false"
- inkscape:snap-object-midpoints="true">
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-midpoints="false"
+ inkscape:snap-others="false">
<inkscape:grid
type="xygrid"
id="grid17394"
@@ -88001,37 +88003,37 @@
<g
style="display:inline;enable-background:new"
id="ICON_COLLAPSEMENU"
- transform="translate(279.8665,506.92392)">
+ transform="translate(280,508)">
<rect
y="111"
x="103"
height="16"
width="16"
id="rect24489-7-4"
- style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;enable-background:accumulate" />
<rect
style="fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1"
id="rect29842"
- width="11.816368"
- height="2.1883197"
- x="105.18671"
- y="-116.88043"
+ width="11.209318"
+ height="2.1883163"
+ x="105.39484"
+ y="-116.60292"
transform="scale(1,-1)" />
<rect
- style="fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1;display:inline;enable-background:new"
+ style="display:inline;fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1;enable-background:new"
id="rect29842-4"
- width="11.816368"
- height="2.1883197"
- x="105.31538"
- y="-120.80865"
+ width="11.191971"
+ height="2.2056611"
+ x="105.41944"
+ y="-120.61786"
transform="scale(1,-1)" />
<rect
- style="fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79452544;stroke-opacity:1;display:inline;enable-background:new"
+ style="display:inline;fill:#ececec;fill-opacity:1;stroke:#141414;stroke-width:0.79500002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;enable-background:new"
id="rect29842-4-5"
- width="11.816368"
- height="2.1883197"
- x="105.41832"
- y="-124.71391"
+ width="11.22666"
+ height="2.2056642"
+ x="105.38363"
+ y="-124.60985"
transform="scale(1,-1)" />
</g>
<g
@@ -89360,17 +89362,18 @@
y="69" />
<g
id="g17605"
- transform="translate(-1.5467961,-0.48613592)">
+ transform="translate(-0.99177519,0.03419629)">
<path
- sodipodi:nodetypes="ccccccccccc"
+ style="fill:url(#linearGradient17610);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 472.51758,370.53516 -1.04688,0.0312 0.0371,9.96875 1.00977,0 3.95117,-3.70704 -5.3e-4,3.72852 3.1119,0 0,-10.01758 -3.1119,0 5.3e-4,3.73242 z"
+ transform="translate(-404.00822,-298.0342)"
+ id="path11011-6"
inkscape:connector-curvature="0"
- d="m 72.839729,82.521675 2.731705,0 0,-10.016275 -2.731705,0 L 72.84,76.59374 68.51011,72.5 67.4632,72.53125 67.5,82.49999 68.51011,82.5 72.84,78.43749 z"
- style="fill:url(#linearGradient17610);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path11011-6" />
+ sodipodi:nodetypes="ccccccccccc" />
<path
sodipodi:nodetypes="ccc"
style="fill:none;stroke:url(#linearGradient17612);stroke-width:0.91056824px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- d="m 73.7503,81.408784 0,-7.99274 0.910568,-6.3e-5"
+ d="m 73.368723,81.408784 0,-7.99274 1.292145,-6.3e-5"
id="path10830-6"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -89397,17 +89400,18 @@
y="69" />
<g
id="g17605-3"
- transform="translate(-1.5467961,-0.48613592)">
+ transform="translate(-1.9392553,-0.11820549)">
<path
- sodipodi:nodetypes="ccccccccccc"
+ style="fill:url(#linearGradient17610-0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 520.5,370.48242 -4.01758,3.80078 -6.6e-4,-3.79492 -3.04231,0 0,10.01563 3.04231,0 6.6e-4,-3.79297 4.01758,3.77148 1.01172,0 0.0371,-9.96875 z"
+ transform="matrix(-1,0,0,1,589.01109,-297.98191)"
+ id="path11011-6-2"
inkscape:connector-curvature="0"
- d="m 72.839729,82.521675 2.731705,0 0,-10.016275 -2.731705,0 L 72.84,76.59374 68.51011,72.5 67.4632,72.53125 67.5,82.49999 68.51011,82.5 72.84,78.43749 z"
- style="fill:url(#linearGradient17610-0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- id="path11011-6-2" />
+ sodipodi:nodetypes="ccccccccccc" />
<path
sodipodi:nodetypes="ccc"
style="fill:none;stroke:url(#linearGradient17612-5);stroke-width:0.91056824px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
- d="m 74.660868,81.408784 0,-7.99274 -0.910568,-6.3e-5"
+ d="m 74.660868,81.408784 0,-7.99274 -1.220453,-6.3e-5"
id="path10830-6-2"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
inkscape:export-xdpi="90"
@@ -89432,16 +89436,16 @@
y="-546"
transform="matrix(0,-1,-1,0,0,0)" />
<path
+ style="fill:url(#linearGradient17165);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 533.51953,371.46094 0,3.04042 3.79492,5.9e-4 -3.77343,4.01953 0,1.01172 9.96875,0.0352 0.0312,-1.04688 -3.80274,-4.01953 3.79688,-5.9e-4 0,-3.04042 z"
id="path11011-6-2-1"
- style="fill:url(#linearGradient17165);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 532.96447,373.70707 0,-2.7317 10.01627,0 0,2.7317 -4.08834,-2.7e-4 4.09374,4.32989 -0.0312,1.04691 -9.96874,-0.0368 -1e-5,-1.01011 4.06251,-4.32989 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc"
id="path11013-5-7-1"
- d="m 541.73615,378.0468 -3.75,-4 -3.75,4"
+ d="m 542.29119,378.53246 -3.75,-4 -3.75,4"
style="fill:none;stroke:url(#linearGradient17162);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
@@ -89449,8 +89453,8 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
id="path10830-6-2-8"
- d="m 542.11634,371.83103 -8.26386,0 -6e-5,0.90043"
- style="fill:none;stroke:url(#linearGradient17838);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 542.67138,372.31669 -8.26386,0 -6e-5,1.20843"
+ style="display:inline;fill:none;stroke:url(#linearGradient17838);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;enable-background:new"
sodipodi:nodetypes="ccc" />
</g>
<g
@@ -89464,16 +89468,16 @@
y="-504"
transform="matrix(0,1,-1,0,0,0)" />
<path
+ style="fill:url(#linearGradient17185);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 501.50977,371.4375 -9.96875,0.0352 0,1.01172 3.69336,3.93554 -3.71485,-0.005 0,3.13033 10.01563,0 0,-3.13033 -3.7168,0.007 3.72266,-3.9375 z"
id="path11011-6-8"
- style="fill:url(#linearGradient17185);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- d="m 490.96446,376.29293 0,2.7317 10.01628,0 0,-2.7317 -4.08834,2.7e-4 4.09374,-4.32989 -0.0312,-1.04691 -9.96874,0.0368 -10e-6,1.01011 4.06251,4.32989 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path11013-5-6"
- d="m 492.23615,371.9532 7.5,0"
+ d="m 492.79119,372.47355 7.5,0"
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
@@ -89481,8 +89485,8 @@
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
id="path10830-6-2-8-8"
- d="m 500.10071,377.17478 -8.26386,0 -6e-5,0.90043"
- style="fill:none;stroke:url(#linearGradient17872);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 500.65575,377.29722 -8.26386,0 -6e-5,1.29834"
+ style="display:inline;fill:none;stroke:url(#linearGradient17872);stroke-width:0.92071104px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;enable-background:new"
sodipodi:nodetypes="ccc" />
</g>
<g
diff --git a/release/datafiles/blender_icons16/icon16_collapsemenu.dat b/release/datafiles/blender_icons16/icon16_collapsemenu.dat
index fd16fadcc8b..246afa11c6c 100644
--- a/release/datafiles/blender_icons16/icon16_collapsemenu.dat
+++ b/release/datafiles/blender_icons16/icon16_collapsemenu.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_down_bar.dat b/release/datafiles/blender_icons16/icon16_tria_down_bar.dat
index 3b734da490a..191f2075b1a 100644
--- a/release/datafiles/blender_icons16/icon16_tria_down_bar.dat
+++ b/release/datafiles/blender_icons16/icon16_tria_down_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_left_bar.dat b/release/datafiles/blender_icons16/icon16_tria_left_bar.dat
index 15826007e7b..e1ea5764367 100644
--- a/release/datafiles/blender_icons16/icon16_tria_left_bar.dat
+++ b/release/datafiles/blender_icons16/icon16_tria_left_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_right_bar.dat b/release/datafiles/blender_icons16/icon16_tria_right_bar.dat
index 75b180afbd7..ce9c3f78ad7 100644
--- a/release/datafiles/blender_icons16/icon16_tria_right_bar.dat
+++ b/release/datafiles/blender_icons16/icon16_tria_right_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tria_up_bar.dat b/release/datafiles/blender_icons16/icon16_tria_up_bar.dat
index b0730cafdd4..e51757d2650 100644
--- a/release/datafiles/blender_icons16/icon16_tria_up_bar.dat
+++ b/release/datafiles/blender_icons16/icon16_tria_up_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_collapsemenu.dat b/release/datafiles/blender_icons32/icon32_collapsemenu.dat
index d84dd843436..788b4009542 100644
--- a/release/datafiles/blender_icons32/icon32_collapsemenu.dat
+++ b/release/datafiles/blender_icons32/icon32_collapsemenu.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_down_bar.dat b/release/datafiles/blender_icons32/icon32_tria_down_bar.dat
index 7a00e79b711..ef6e86ba154 100644
--- a/release/datafiles/blender_icons32/icon32_tria_down_bar.dat
+++ b/release/datafiles/blender_icons32/icon32_tria_down_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_left_bar.dat b/release/datafiles/blender_icons32/icon32_tria_left_bar.dat
index 591b2e2b1bd..a1d48baf971 100644
--- a/release/datafiles/blender_icons32/icon32_tria_left_bar.dat
+++ b/release/datafiles/blender_icons32/icon32_tria_left_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_right_bar.dat b/release/datafiles/blender_icons32/icon32_tria_right_bar.dat
index 1dae635d600..4f687537658 100644
--- a/release/datafiles/blender_icons32/icon32_tria_right_bar.dat
+++ b/release/datafiles/blender_icons32/icon32_tria_right_bar.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tria_up_bar.dat b/release/datafiles/blender_icons32/icon32_tria_up_bar.dat
index 1c7b3072f31..e6c5d5561cd 100644
--- a/release/datafiles/blender_icons32/icon32_tria_up_bar.dat
+++ b/release/datafiles/blender_icons32/icon32_tria_up_bar.dat
Binary files differ
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject 88158191df4da2109bbfd9b0816d891bbc7fc78
+Subproject c93ed11a47b3016cf59711ec16de2e2e94c30e9
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject a746a84f8aaf3a4843eb3f4ce3f5a0464872077
+Subproject 371960484a38fc64e0a2635170a41a0d8ab2f6b
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject 029103debce43110f93295d7633931ec100d301
+Subproject a8515cfdfe9a98127b592f36fcbe51b7e23b969
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index c48f03c133d..d740137b0c3 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -103,9 +103,9 @@ def add_object_align_init(context, operator):
return location * rotation
-def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None):
+def object_data_add(context, obdata, operator=None, name=None):
"""
- Add an object using the view context and preference to to initialize the
+ Add an object using the view context and preference to initialize the
location, rotation and layer.
:arg context: The context to use.
@@ -117,52 +117,24 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
:arg name: Optional name
:type name: string
:return: the newly created object in the scene.
- :rtype: :class:`bpy.types.ObjectBase`
+ :rtype: :class:`bpy.types.Object`
"""
scene = context.scene
+ layer = context.render_layer
+ scene_collection = context.scene_collection
- # ugh, could be made nicer
- for ob in scene.objects:
- ob.select = False
+ bpy.ops.object.select_all(action='DESELECT')
if name is None:
name = "Object" if obdata is None else obdata.name
obj_new = bpy.data.objects.new(name, obdata)
-
- base = scene.objects.link(obj_new)
- base.select = True
-
- v3d = None
- if context.space_data and context.space_data.type == 'VIEW_3D':
- v3d = context.space_data
-
- if v3d and v3d.local_view:
- base.layers_from_view(context.space_data)
-
- if operator is not None and any(operator.layers):
- base.layers = operator.layers
- else:
- if use_active_layer:
- if v3d and v3d.local_view:
- base.layers[scene.active_layer] = True
- else:
- if v3d and not v3d.lock_camera_and_layers:
- base.layers = [True if i == v3d.active_layer
- else False for i in range(len(v3d.layers))]
- else:
- base.layers = [True if i == scene.active_layer
- else False for i in range(len(scene.layers))]
- else:
- if v3d:
- base.layers_from_view(context.space_data)
-
- if operator is not None:
- operator.layers = base.layers
+ scene_collection.objects.link(obj_new)
+ obj_new.select_set(action='SELECT')
obj_new.matrix_world = add_object_align_init(context, operator)
- obj_act = scene.objects.active
+ obj_act = layer.objects.active
# XXX
# caused because entering edit-mode does not add a empty undo slot!
@@ -174,8 +146,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
_obdata = bpy.data.meshes.new(name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
- scene.objects.link(obj_act)
- scene.objects.active = obj_act
+ scene_collection.objects.link(obj_act)
+ layer.objects.active = obj_act
bpy.ops.object.mode_set(mode='EDIT')
# need empty undo step
bpy.ops.ed.undo_push(message="Enter Editmode")
@@ -185,7 +157,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT')
- obj_act.select = True
+ obj_act.select_set(action='SELECT')
scene.update() # apply location
# scene.objects.active = obj_new
@@ -200,16 +172,14 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
bpy.ops.object.join() # join into the active.
if obdata:
bpy.data.meshes.remove(obdata)
- # base is freed, set to active object
- base = scene.object_bases.active
bpy.ops.object.mode_set(mode='EDIT')
else:
- scene.objects.active = obj_new
+ layer.objects.active = obj_new
if context.user_preferences.edit.use_enter_edit_mode:
bpy.ops.object.mode_set(mode='EDIT')
- return base
+ return obj_new
class AddObjectHelper:
@@ -230,12 +200,6 @@ class AddObjectHelper:
name="Rotation",
subtype='EULER',
)
- layers = BoolVectorProperty(
- name="Layers",
- size=20,
- subtype='LAYER',
- options={'HIDDEN', 'SKIP_SAVE'},
- )
@classmethod
def poll(self, context):
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
index 7694e338d68..b6b0a0c926f 100644
--- a/release/scripts/presets/keyconfig/3dsmax.py
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -330,7 +330,6 @@ kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
kmi = km.keymap_items.new('object.hide_render_clear', 'H', 'PRESS', ctrl=True, alt=True)
kmi = km.keymap_items.new('object.hide_render_set', 'H', 'PRESS', ctrl=True)
-kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'X', 'PRESS')
kmi.properties.use_global = False
kmi = km.keymap_items.new('object.delete', 'X', 'PRESS', shift=True)
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index 67fd1fddcac..f542ecf810b 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -384,7 +384,6 @@ kmi = km.keymap_items.new('object.hide_view_clear', 'H', 'PRESS', shift=True, ct
kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', alt=True)
kmi.properties.unselected = True
-kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'BACK_SPACE', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS')
kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py
index 0c77ea2ab7e..d60703236d6 100644
--- a/release/scripts/startup/bl_operators/clip.py
+++ b/release/scripts/startup/bl_operators/clip.py
@@ -232,7 +232,7 @@ class CLIP_OT_track_to_empty(Operator):
ob = None
ob = bpy.data.objects.new(name=track.name, object_data=None)
- ob.select = True
+ ob.select_set(action='SELECT')
context.scene.objects.link(ob)
context.scene.objects.active = ob
@@ -506,7 +506,7 @@ object's movement caused by this constraint"""
# XXX, should probably use context.selected_editable_objects
# since selected objects can be from a lib or in hidden layer!
for ob in scene.objects:
- if ob.select:
+ if ob.select_set(action='SELECT'):
self._bake_object(scene, ob)
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py
index edda92284d2..43cd3110beb 100644
--- a/release/scripts/startup/bl_operators/freestyle.py
+++ b/release/scripts/startup/bl_operators/freestyle.py
@@ -62,31 +62,69 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
m = linestyle.alpha_modifiers[self.name]
else:
m = linestyle.thickness_modifiers[self.name]
- # Find the source object
+ # Find the reference object
if m.type == 'DISTANCE_FROM_CAMERA':
- source = scene.camera
+ ref = scene.camera
+ matrix_to_camera = ref.matrix_world.inverted()
elif m.type == 'DISTANCE_FROM_OBJECT':
if m.target is None:
self.report({'ERROR'}, "Target object not specified")
return {'CANCELLED'}
- source = m.target
+ ref = m.target
+ target_location = ref.location
else:
self.report({'ERROR'}, "Unexpected modifier type: " + m.type)
return {'CANCELLED'}
- # Find selected mesh objects
- selection = [ob for ob in scene.objects if ob.select and ob.type == 'MESH' and ob.name != source.name]
- if selection:
- # Compute the min/max distance between selected mesh objects and the source
+ # Find selected vertices in editmesh
+ ob = bpy.context.active_object
+ if ob.type == 'MESH' and ob.mode == 'EDIT' and ob.name != ref.name:
+ bpy.ops.object.mode_set(mode='OBJECT')
+ selected_verts = [v for v in bpy.context.active_object.data.vertices if v.select]
+ bpy.ops.object.mode_set(mode='EDIT')
+ # Compute the min/max distance from the reference to mesh vertices
min_dist = sys.float_info.max
max_dist = -min_dist
- for ob in selection:
- for vert in ob.data.vertices:
- dist = (ob.matrix_world * vert.co - source.location).length
+ if m.type == 'DISTANCE_FROM_CAMERA':
+ ob_to_cam = matrix_to_camera * ob.matrix_world
+ for vert in selected_verts:
+ # dist in the camera space
+ dist = (ob_to_cam * vert.co).length
+ min_dist = min(dist, min_dist)
+ max_dist = max(dist, max_dist)
+ elif m.type == 'DISTANCE_FROM_OBJECT':
+ for vert in selected_verts:
+ # dist in the world space
+ dist = (ob.matrix_world * vert.co - target_location).length
min_dist = min(dist, min_dist)
max_dist = max(dist, max_dist)
# Fill the Range Min/Max entries with the computed distances
m.range_min = min_dist
m.range_max = max_dist
+ return {'FINISHED'}
+ # Find selected mesh objects
+ selection = [ob for ob in scene.objects if ob.select_get() and ob.type == 'MESH' and ob.name != source.name]
+ if selection:
+ # Compute the min/max distance from the reference to mesh vertices
+ min_dist = sys.float_info.max
+ max_dist = -min_dist
+ if m.type == 'DISTANCE_FROM_CAMERA':
+ for ob in selection:
+ ob_to_cam = matrix_to_camera * ob.matrix_world
+ for vert in ob.data.vertices:
+ # dist in the camera space
+ dist = (ob_to_cam * vert.co).length
+ min_dist = min(dist, min_dist)
+ max_dist = max(dist, max_dist)
+ elif m.type == 'DISTANCE_FROM_OBJECT':
+ for ob in selection:
+ for vert in ob.data.vertices:
+ # dist in the world space
+ dist = (ob.matrix_world * vert.co - target_location).length
+ min_dist = min(dist, min_dist)
+ max_dist = max(dist, max_dist)
+ # Fill the Range Min/Max entries with the computed distances
+ m.range_min = min_dist
+ m.range_max = max_dist
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 6356da216b1..be680a6df0c 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -81,16 +81,18 @@ class SelectPattern(Operator):
# Can be pose bones or objects
for item in items:
if pattern_match(item.name, self.pattern):
- item.select = True
# hrmf, perhaps there should be a utility function for this.
if is_ebone:
+ item.select = True
item.select_head = True
item.select_tail = True
if item.use_connect:
item_parent = item.parent
if item_parent is not None:
item_parent.select_tail = True
+ else:
+ item.select_set(action='SELECT')
return {'FINISHED'}
@@ -136,7 +138,7 @@ class SelectCamera(Operator):
bpy.ops.object.select_all(action='DESELECT')
scene.objects.active = camera
camera.hide = False
- camera.select = True
+ camera.select_set(action='SELECT')
return {'FINISHED'}
return {'CANCELLED'}
@@ -202,7 +204,7 @@ class SelectHierarchy(Operator):
bpy.ops.object.select_all(action='DESELECT')
for obj in select_new:
- obj.select = True
+ obj.select_set(action='SELECT')
scene.objects.active = act_new
return {'FINISHED'}
@@ -644,8 +646,8 @@ class MakeDupliFace(Operator):
ob_new.use_dupli_faces_scale = True
ob_new.dupli_faces_scale = 1.0 / SCALE_FAC
- ob_inst.select = True
- ob_new.select = True
+ ob_inst.select_set(action='SELECT')
+ ob_new.select_set(action='SELECT')
def execute(self, context):
self._main(context)
@@ -664,7 +666,7 @@ class IsolateTypeRender(Operator):
for obj in context.visible_objects:
- if obj.select:
+ if obj.select_get():
obj.hide_render = False
else:
if obj.type == act_type:
@@ -1029,8 +1031,8 @@ class LodGenerate(Operator):
for level in ob.lod_levels[1:]:
level.object.hide = level.object.hide_render = True
- lod.select = False
- ob.select = True
+ lod.select_set(action='DESELECT')
+ ob.select_set(action='SELECT')
scene.objects.active = ob
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
index 750a5b0bf0f..cba49c629be 100644
--- a/release/scripts/startup/bl_operators/rigidbody.py
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -63,7 +63,7 @@ class CopyRigidbodySettings(Operator):
# deselect all but mesh objects
for o in context.selected_objects:
if o.type != 'MESH':
- o.select = False
+ o.select_set(action='DESELECT')
elif o.rigid_body is None:
# Add rigidbody to object!
scene.objects.active = o
@@ -125,7 +125,7 @@ class BakeToKeyframes(Operator):
# filter objects selection
for obj in context.selected_objects:
if not obj.rigid_body or obj.rigid_body.type != 'ACTIVE':
- obj.select = False
+ obj.select_set(action='DESELECT')
objects = context.selected_objects
@@ -258,7 +258,7 @@ class ConnectRigidBodies(Operator):
ob.location = loc
context.scene.objects.link(ob)
context.scene.objects.active = ob
- ob.select = True
+ ob.select_set(action='SELECT')
bpy.ops.rigidbody.constraint_add()
con_obj = context.active_object
@@ -303,7 +303,7 @@ class ConnectRigidBodies(Operator):
# restore selection
bpy.ops.object.select_all(action='DESELECT')
for obj in objects:
- obj.select = True
+ obj.select_set(action='SELECT')
scene.objects.active = obj_act
return {'FINISHED'}
else:
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 2389be6787d..0f26ff75715 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -29,6 +29,7 @@ if "bpy" in locals():
_modules = [
"properties_animviz",
+ "properties_collection",
"properties_constraint",
"properties_data_armature",
"properties_data_bone",
@@ -69,6 +70,7 @@ _modules = [
"space_graph",
"space_image",
"space_info",
+ "space_collections",
"space_logic",
"space_nla",
"space_node",
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py
new file mode 100644
index 00000000000..88d78f98ef2
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_collection.py
@@ -0,0 +1,128 @@
+# ##### 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, UIList
+
+
+class CollectionButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "collection"
+
+
+class COLLECTION_PT_context_collection(CollectionButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+
+ def draw(self, context):
+ layout = self.layout
+ space = context.space_data
+
+ collection = context.layer_collection
+ name = collection.name
+ if name == 'Master Collection':
+ layout.label(text=name, icon='COLLAPSEMENU')
+ else:
+ layout.prop(collection, "name", text="", icon='COLLAPSEMENU')
+
+
+class COLLECTION_UL_objects(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.Object)
+ ob = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(ob.name, icon_value=icon)
+
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+
+class COLLECTION_PT_objects(CollectionButtonsPanel, Panel):
+ bl_label = "Objects"
+
+ def draw(self, context):
+ layout = self.layout
+ scene = context.scene
+ collection = context.scene_collection
+
+ row = layout.row()
+ row.template_list("COLLECTION_UL_objects", "name", collection, "objects", collection.objects, "active_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("collections.objects_add", icon='ZOOMIN', text="")
+ col.operator("collections.objects_remove", icon='ZOOMOUT', text="")
+
+ row = layout.row(align=True)
+ row.operator("collections.objects_select", text="Select")
+ row.operator("collections.objects_deselect", text="Deselect")
+
+
+def template_engine_settings(col, settings, name, use_icon_view=False):
+ icons = {
+ False: 'ZOOMIN',
+ True: 'X',
+ }
+
+ use_name = "{0}_use".format(name)
+ use = getattr(settings, use_name)
+
+ row = col.row()
+ col = row.column()
+ col.active = use
+
+ if use_icon_view:
+ col.template_icon_view(settings, name)
+ else:
+ col.prop(settings, name)
+
+ row.prop(settings, "{}_use".format(name), text="", icon=icons[use], emboss=False)
+
+
+class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel):
+ bl_label = "Render Settings"
+ COMPAT_ENGINES = {'BLENDER_CLAY'}
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ return scene and (scene.render.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ collection = context.layer_collection
+ settings = collection.get_engine_settings()
+
+ col = layout.column()
+ template_engine_settings(col, settings, "type")
+ template_engine_settings(col, settings, "matcap_icon", use_icon_view=True)
+ template_engine_settings(col, settings, "matcap_rotation")
+ template_engine_settings(col, settings, "matcap_hue")
+ template_engine_settings(col, settings, "matcap_saturation")
+ template_engine_settings(col, settings, "matcap_value")
+ template_engine_settings(col, settings, "ssao_factor_cavity")
+ template_engine_settings(col, settings, "ssao_factor_edge")
+ template_engine_settings(col, settings, "ssao_distance")
+ template_engine_settings(col, settings, "ssao_attenuation")
+
+
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 4d54817a21c..ec061370fe5 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -469,8 +469,86 @@ class SceneButtonsPanel:
bl_context = "scene"
+class SCENE_PT_game_physics(SceneButtonsPanel, Panel):
+ bl_label = "Physics"
+ COMPAT_ENGINES = {'BLENDER_GAME'}
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ return (scene.render.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ gs = context.scene.game_settings
+
+ layout.prop(gs, "physics_engine", text="Engine")
+ if gs.physics_engine != 'NONE':
+ layout.prop(gs, "physics_gravity", text="Gravity")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Physics Steps:")
+ sub = col.column(align=True)
+ sub.prop(gs, "physics_step_max", text="Max")
+ sub.prop(gs, "physics_step_sub", text="Substeps")
+ col.prop(gs, "fps", text="FPS")
+
+ col = split.column()
+ col.label(text="Logic Steps:")
+ col.prop(gs, "logic_step_max", text="Max")
+
+ col = layout.column()
+ col.label(text="Physics Deactivation:")
+ sub = col.row(align=True)
+ sub.prop(gs, "deactivation_linear_threshold", text="Linear Threshold")
+ sub.prop(gs, "deactivation_angular_threshold", text="Angular Threshold")
+ sub = col.row()
+ sub.prop(gs, "deactivation_time", text="Time")
+
+ col = layout.column()
+ col.prop(gs, "use_occlusion_culling", text="Occlusion Culling")
+ sub = col.column()
+ sub.active = gs.use_occlusion_culling
+ sub.prop(gs, "occlusion_culling_resolution", text="Resolution")
+
+ else:
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Physics Steps:")
+ col.prop(gs, "fps", text="FPS")
+
+ col = split.column()
+ col.label(text="Logic Steps:")
+ col.prop(gs, "logic_step_max", text="Max")
+
+
+class SCENE_PT_game_physics_obstacles(SceneButtonsPanel, Panel):
+ bl_label = "Obstacle Simulation"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_GAME'}
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ return (scene.render.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ gs = context.scene.game_settings
+
+ layout.prop(gs, "obstacle_simulation", text="Type")
+ if gs.obstacle_simulation != 'NONE':
+ layout.prop(gs, "level_height")
+ layout.prop(gs, "show_obstacle_simulation")
+
+
class SCENE_PT_game_navmesh(SceneButtonsPanel, Panel):
- bl_label = "Navigation mesh"
+ bl_label = "Navigation Mesh"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -484,7 +562,7 @@ class SCENE_PT_game_navmesh(SceneButtonsPanel, Panel):
rd = context.scene.game_settings.recast_data
- layout.operator("mesh.navmesh_make", text="Build navigation mesh")
+ layout.operator("mesh.navmesh_make", text="Build Navigation Mesh")
col = layout.column()
col.label(text="Rasterization:")
@@ -656,83 +734,6 @@ class WORLD_PT_game_mist(WorldButtonsPanel, Panel):
layout.prop(world.mist_settings, "intensity", text="Minimum Intensity")
-class WORLD_PT_game_physics(WorldButtonsPanel, Panel):
- bl_label = "Physics"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
-
- layout.prop(gs, "physics_engine", text="Engine")
- if gs.physics_engine != 'NONE':
- layout.prop(gs, "physics_gravity", text="Gravity")
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Physics Steps:")
- sub = col.column(align=True)
- sub.prop(gs, "physics_step_max", text="Max")
- sub.prop(gs, "physics_step_sub", text="Substeps")
- col.prop(gs, "fps", text="FPS")
-
- col = split.column()
- col.label(text="Logic Steps:")
- col.prop(gs, "logic_step_max", text="Max")
-
- col = layout.column()
- col.label(text="Physics Deactivation:")
- sub = col.row(align=True)
- sub.prop(gs, "deactivation_linear_threshold", text="Linear Threshold")
- sub.prop(gs, "deactivation_angular_threshold", text="Angular Threshold")
- sub = col.row()
- sub.prop(gs, "deactivation_time", text="Time")
-
- col = layout.column()
- col.prop(gs, "use_occlusion_culling", text="Occlusion Culling")
- sub = col.column()
- sub.active = gs.use_occlusion_culling
- sub.prop(gs, "occlusion_culling_resolution", text="Resolution")
-
- else:
- split = layout.split()
-
- col = split.column()
- col.label(text="Physics Steps:")
- col.prop(gs, "fps", text="FPS")
-
- col = split.column()
- col.label(text="Logic Steps:")
- col.prop(gs, "logic_step_max", text="Max")
-
-
-class WORLD_PT_game_physics_obstacles(WorldButtonsPanel, Panel):
- bl_label = "Obstacle Simulation"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
-
- layout.prop(gs, "obstacle_simulation", text="Type")
- if gs.obstacle_simulation != 'NONE':
- layout.prop(gs, "level_height")
- layout.prop(gs, "show_obstacle_simulation")
-
-
class DataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 850606eb80b..90d46a6ee47 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -377,7 +377,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
sub.active = rd.use_stamp_note
sub.prop(rd, "stamp_note_text", text="")
if rd.use_sequencer:
- layout.label("Sequencer")
+ layout.label("Sequencer:")
layout.prop(rd, "use_stamp_strip_meta")
@@ -584,5 +584,24 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
sub.prop(rd, "bake_user_scale", text="User Scale")
+class RENDER_PT_clay(RenderButtonsPanel, Panel):
+ bl_label = "Default Clay"
+ COMPAT_ENGINES = {'BLENDER_CLAY'}
+
+ def draw(self, context):
+ layout = self.layout;
+ settings = context.scene.active_engine_settings
+ layout.template_icon_view(settings, "matcap_icon")
+ layout.prop(settings, "matcap_rotation")
+ layout.prop(settings, "matcap_hue")
+ layout.prop(settings, "matcap_saturation")
+ layout.prop(settings, "matcap_value")
+ layout.prop(settings, "ssao_factor_cavity")
+ layout.prop(settings, "ssao_factor_edge")
+ layout.prop(settings, "ssao_distance")
+ layout.prop(settings, "ssao_attenuation")
+ layout.prop(settings, "ssao_samples")
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
index 9b8bc237db9..2545eadc792 100644
--- a/release/scripts/startup/bl_ui/properties_render_layer.py
+++ b/release/scripts/startup/bl_ui/properties_render_layer.py
@@ -35,7 +35,7 @@ class RenderLayerButtonsPanel:
class RENDERLAYER_UL_renderlayers(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.SceneRenderLayer)
+ # assert(isinstance(item, bpy.types.SceneLayer)
layer = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(layer, "name", text="", icon_value=icon, emboss=False)
@@ -48,7 +48,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
bl_label = "Layer List"
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -62,7 +62,7 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
+ col.template_list("RENDERLAYER_UL_renderlayers", "", scene, "render_layers", scene.render_layers, "active_index", rows=2)
col = row.column()
sub = col.column(align=True)
@@ -71,103 +71,6 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
col.prop(rd, "use_single_layer", icon_only=True)
-class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel):
- bl_label = "Layer"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- rl = rd.layers.active
-
- split = layout.split()
-
- col = split.column()
- col.prop(scene, "layers", text="Scene")
- col.label(text="")
- col.prop(rl, "light_override", text="Lights")
- col.prop(rl, "material_override", text="Material")
-
- col = split.column()
- col.prop(rl, "layers", text="Layer")
- col.prop(rl, "layers_zmask", text="Mask Layer")
-
- layout.separator()
- layout.label(text="Include:")
-
- split = layout.split()
-
- col = split.column()
- col.prop(rl, "use_zmask")
- row = col.row()
- row.prop(rl, "invert_zmask", text="Negate")
- row.active = rl.use_zmask
- col.prop(rl, "use_all_z")
-
- col = split.column()
- col.prop(rl, "use_solid")
- col.prop(rl, "use_halo")
- col.prop(rl, "use_ztransp")
-
- col = split.column()
- col.prop(rl, "use_sky")
- col.prop(rl, "use_edge_enhance")
- col.prop(rl, "use_strand")
- if bpy.app.build_options.freestyle:
- row = col.row()
- row.prop(rl, "use_freestyle")
- row.active = rd.use_freestyle
-
-
-class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
- bl_label = "Passes"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @staticmethod
- def draw_pass_type_buttons(box, rl, pass_type):
- # property names
- use_pass_type = "use_pass_" + pass_type
- exclude_pass_type = "exclude_" + pass_type
- # draw pass type buttons
- row = box.row()
- row.prop(rl, use_pass_type)
- row.prop(rl, exclude_pass_type, text="")
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- rl = rd.layers.active
-
- split = layout.split()
-
- col = split.column()
- col.prop(rl, "use_pass_combined")
- col.prop(rl, "use_pass_z")
- col.prop(rl, "use_pass_vector")
- col.prop(rl, "use_pass_normal")
- col.prop(rl, "use_pass_uv")
- col.prop(rl, "use_pass_mist")
- col.prop(rl, "use_pass_object_index")
- col.prop(rl, "use_pass_material_index")
- col.prop(rl, "use_pass_color")
-
- col = split.column()
- col.prop(rl, "use_pass_diffuse")
- self.draw_pass_type_buttons(col, rl, "specular")
- self.draw_pass_type_buttons(col, rl, "shadow")
- self.draw_pass_type_buttons(col, rl, "emit")
- self.draw_pass_type_buttons(col, rl, "ambient_occlusion")
- self.draw_pass_type_buttons(col, rl, "environment")
- self.draw_pass_type_buttons(col, rl, "indirect")
- self.draw_pass_type_buttons(col, rl, "reflection")
- self.draw_pass_type_buttons(col, rl, "refraction")
-
-
class RENDERLAYER_UL_renderviews(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.SceneRenderView)
diff --git a/release/scripts/startup/bl_ui/space_collections.py b/release/scripts/startup/bl_ui/space_collections.py
new file mode 100644
index 00000000000..9b612ce2ecd
--- /dev/null
+++ b/release/scripts/startup/bl_ui/space_collections.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Header, Menu
+
+
+class COLLECTIONS_HT_header(Header):
+ bl_space_type = 'COLLECTION_MANAGER'
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.template_header()
+
+ row = layout.row(align=True)
+ row.operator("collections.collection_new", text="", icon='NEW')
+ row.operator("collections.override_new", text="", icon='LINK_AREA')
+ row.operator("collections.collection_link", text="", icon='LINKED')
+ row.operator("collections.collection_unlink", text="", icon='UNLINKED')
+ row.operator("collections.delete", text="", icon='X')
+
+
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 6f7c535fe21..eb3cef8012d 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -59,6 +59,14 @@ class OUTLINER_HT_header(Header):
row.label(text="No Keying Set active")
elif space.display_mode == 'ORPHAN_DATA':
layout.operator("outliner.orphans_purge")
+ elif space.display_mode == 'COLLECTIONS':
+ row = layout.row(align=True)
+
+ row.operator("collections.collection_new", text="", icon='NEW')
+ row.operator("collections.override_new", text="", icon='LINK_AREA')
+ row.operator("collections.collection_link", text="", icon='LINKED')
+ row.operator("collections.collection_unlink", text="", icon='UNLINKED')
+ row.operator("collections.delete", text="", icon='X')
class OUTLINER_MT_editor_menus(Menu):
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index f8e4d1338f9..f605712510a 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -634,7 +634,6 @@ class VIEW3D_MT_select_object(Menu):
layout.operator("object.select_all", text="Inverse").action = 'INVERT'
layout.operator("object.select_random", text="Random")
layout.operator("object.select_mirror", text="Mirror")
- layout.operator("object.select_by_layer", text="Select All by Layer")
layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
layout.operator("object.select_camera", text="Select Camera")
@@ -1311,15 +1310,6 @@ class VIEW3D_MT_object(Menu):
layout.separator()
- if is_local_view:
- layout.operator_context = 'EXEC_REGION_WIN'
- layout.operator("object.move_to_layer", text="Move out of Local View")
- layout.operator_context = 'INVOKE_REGION_WIN'
- else:
- layout.operator("object.move_to_layer", text="Move to Layer...")
-
- layout.menu("VIEW3D_MT_object_showhide")
-
layout.operator_menu_enum("object.convert", "target")
@@ -1345,9 +1335,9 @@ class VIEW3D_MT_object_clear(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("object.location_clear", text="Location")
- layout.operator("object.rotation_clear", text="Rotation")
- layout.operator("object.scale_clear", text="Scale")
+ layout.operator("object.location_clear", text="Location").clear_delta = False
+ layout.operator("object.rotation_clear", text="Rotation").clear_delta = False
+ layout.operator("object.scale_clear", text="Scale").clear_delta = False
layout.operator("object.origin_clear", text="Origin")
@@ -1597,17 +1587,6 @@ class VIEW3D_MT_object_quick_effects(Menu):
layout.operator("object.quick_fluid")
-class VIEW3D_MT_object_showhide(Menu):
- bl_label = "Show/Hide"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("object.hide_view_clear", text="Show Hidden")
- layout.operator("object.hide_view_set", text="Hide Selected").unselected = False
- layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True
-
-
class VIEW3D_MT_make_single_user(Menu):
bl_label = "Make Single User"
@@ -3167,6 +3146,74 @@ class VIEW3D_PT_viewport_debug(Panel):
col.row(align=True).prop(view, "debug_background", expand=True)
+class VIEW3D_PT_collections_editor(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+ bl_label = "Collections"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.space_data
+
+ def draw(self, context):
+ layout = self.layout
+ layer = context.render_layer
+ active_collection = context.layer_collection
+
+ col = layout.column()
+ box = col.box()
+
+ index = -1
+ for collection in layer.collections:
+ index = self._draw_layer_collection(box, index, active_collection, collection, True, True)
+
+ row = layout.row(align=True)
+ row.operator("collections.collection_new", text="", icon='NEW')
+ row.operator("collections.override_new", text="", icon='LINK_AREA')
+ row.operator("collections.collection_link", text="", icon='LINKED')
+ row.operator("collections.collection_unlink", text="", icon='UNLINKED')
+ row.operator("collections.delete", text="", icon='X')
+
+ def _draw_layer_collection(self, box, index, active_collection, collection, is_active, is_draw, depth=0):
+ index += 1
+ nested_collections = collection.collections
+
+ if is_draw:
+ row = box.row()
+ row.active = is_active
+ is_collection_selected = (collection == active_collection)
+
+ if is_collection_selected:
+ sub_box = row.box()
+ row = sub_box.row()
+
+ row.label(text="{0}{1}{2}".format(
+ " " * depth,
+ u'\u21b3 ' if depth else "",
+ collection.name))
+
+ row.prop(collection, "hide", text="", emboss=False)
+ row.prop(collection, "hide_select", text="", emboss=False)
+
+ row.operator("collections.select", text="", icon='BLANK1' if is_collection_selected else 'HAND', emboss=False).collection_index=index
+
+ if nested_collections:
+ row.prop(collection, "is_unfolded", text="", emboss=False)
+ else:
+ row.label(icon='BLANK1')
+
+ if not collection.is_unfolded:
+ is_draw = False
+
+ is_active &= not collection.hide
+
+ for nested_collection in nested_collections:
+ index = self._draw_layer_collection(box, index, active_collection, nested_collection, is_active, is_draw, depth + 1)
+
+ return index
+
+
class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py
index 6c77c5d6a1a..8de7a5e2903 100644
--- a/release/scripts/templates_py/batch_export.py
+++ b/release/scripts/templates_py/batch_export.py
@@ -18,7 +18,7 @@ bpy.ops.object.select_all(action='DESELECT')
for obj in selection:
- obj.select = True
+ obj.select_set(action='SELECT')
# some exporters only use the active object
scene.objects.active = obj
@@ -31,7 +31,7 @@ for obj in selection:
## Can be used for multiple formats
# bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
- obj.select = False
+ obj.select_set(action='DESELECT')
print("written:", fn)
@@ -39,4 +39,4 @@ for obj in selection:
scene.objects.active = obj_active
for obj in selection:
- obj.select = True
+ obj.select_set(action='SELECT')
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index c4d661b4c1f..e3b63813fc4 100644
--- a/release/scripts/templates_py/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -67,7 +67,7 @@ def main(context, event):
# now we have the object under the mouse cursor,
# we could do lots of stuff but for the example just select.
if best_obj is not None:
- best_obj.select = True
+ best_obj.select_set(action='SELECT')
context.scene.objects.active = best_obj
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 6f2b78e0845..47ebed8f791 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -100,6 +100,7 @@ add_subdirectory(windowmanager)
add_subdirectory(blenkernel)
add_subdirectory(blenlib)
add_subdirectory(bmesh)
+add_subdirectory(draw)
add_subdirectory(render)
add_subdirectory(blenfont)
add_subdirectory(blentranslation)
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc
index 4ecb9d944f2..282777f3af0 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_curves.cc
@@ -102,7 +102,7 @@ void AbcCurveWriter::do_write()
const BPoint *point = nurbs->bp;
for (int i = 0; i < totpoint; ++i, ++point) {
- copy_zup_yup(temp_vert.getValue(), point->vec);
+ copy_yup_from_zup(temp_vert.getValue(), point->vec);
verts.push_back(temp_vert);
weights.push_back(point->vec[3]);
widths.push_back(point->radius);
@@ -118,7 +118,7 @@ void AbcCurveWriter::do_write()
/* TODO(kevin): store info about handles, Alembic doesn't have this. */
for (int i = 0; i < totpoint; ++i, ++bezier) {
- copy_zup_yup(temp_vert.getValue(), bezier->vec[1]);
+ copy_yup_from_zup(temp_vert.getValue(), bezier->vec[1]);
verts.push_back(temp_vert);
widths.push_back(bezier->radius);
}
@@ -322,7 +322,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
weight = (*weights)[idx];
}
- copy_yup_zup(bp->vec, pos.getValue());
+ copy_zup_from_yup(bp->vec, pos.getValue());
bp->vec[3] = weight;
bp->f1 = SELECT;
bp->radius = radius;
@@ -389,7 +389,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t
for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) {
const Imath::V3f &pos = (*positions)[vertex_idx];
- copy_yup_zup(point->vec, pos.getValue());
+ copy_zup_from_yup(point->vec, pos.getValue());
}
}
else if (nurbs->bezt) {
@@ -397,7 +397,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t
for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) {
const Imath::V3f &pos = (*positions)[vertex_idx];
- copy_yup_zup(bezier->vec[1], pos.getValue());
+ copy_zup_from_yup(bezier->vec[1], pos.getValue());
}
}
}
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index ff8b0442ab6..28d54672d20 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -123,19 +123,19 @@ static bool object_is_shape(Object *ob)
}
}
-static bool export_object(const ExportSettings * const settings, Object *ob)
+static bool export_object(const ExportSettings * const settings, const Base * const ob_base)
{
- if (settings->selected_only && !parent_selected(ob)) {
+ if (settings->selected_only && !object_selected(ob_base)) {
return false;
}
-
- if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) {
+ // FIXME Sybren: handle these cleanly (maybe just remove code), now using active scene layer instead.
+ if (settings->visible_layers_only && (ob_base->flag & BASE_VISIBLED) == 0) {
return false;
}
- if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
- return false;
- }
+ // if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
+ // return false;
+ // }
return true;
}
@@ -341,12 +341,10 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
{
- Base *base = static_cast<Base *>(m_scene->base.first);
-
- while (base) {
+ for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
Object *ob = base->object;
- if (export_object(&m_settings, ob)) {
+ if (export_object(&m_settings, base)) {
switch(ob->type) {
case OB_LAMP:
case OB_LATTICE:
@@ -356,50 +354,49 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
break;
default:
- exploreTransform(eval_ctx, ob, ob->parent, NULL);
+ exploreTransform(eval_ctx, base, ob->parent, NULL);
}
}
-
- base = base->next;
}
}
void AbcExporter::createTransformWritersFlat()
{
- Base *base = static_cast<Base *>(m_scene->base.first);
-
- while (base) {
+ for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
Object *ob = base->object;
- if (export_object(&m_settings, ob) && object_is_shape(ob)) {
+ if (!export_object(&m_settings, base)) {
std::string name = get_id_name(ob);
m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), 0, m_trans_sampling_index, m_settings);
}
-
- base = base->next;
}
}
-void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent)
+void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent)
{
- createTransformWriter(ob, parent, dupliObParent);
+ Object *ob = ob_base->object;
+
+ if (export_object(&m_settings, ob_base) && object_is_shape(ob)) {
+ createTransformWriter(ob, parent, dupliObParent);
+ }
ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
if (lb) {
- DupliObject *link = static_cast<DupliObject *>(lb->first);
- Object *dupli_ob = NULL;
- Object *dupli_parent = NULL;
-
- while (link) {
+ Base fake_base = *ob_base; // copy flags (like selection state) from the real object.
+ fake_base.next = fake_base.prev = NULL;
+
+ for (DupliObject *link = static_cast<DupliObject *>(lb->first); link; link = link->next) {
+ Object *dupli_ob = NULL;
+ Object *dupli_parent = NULL;
+
if (link->type == OB_DUPLIGROUP) {
dupli_ob = link->ob;
dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob;
- exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob);
+ fake_base.object = dupli_ob;
+ exploreTransform(eval_ctx, &fake_base, dupli_parent, ob);
}
-
- link = link->next;
}
}
@@ -410,8 +407,12 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
{
const std::string name = get_object_dag_path_name(ob, dupliObParent);
+ /* An object should not be its own parent, or we'll get infinite loops. */
+ BLI_assert(ob != parent);
+ BLI_assert(ob != dupliObParent);
+
/* check if we have already created a transform writer for this object */
- if (m_xforms.find(name) != m_xforms.end()){
+ if (getXForm(name) != NULL){
std::cerr << "xform " << name << " already exists\n";
return;
}
@@ -426,6 +427,14 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
if (parent->parent) {
createTransformWriter(parent, parent->parent, dupliObParent);
}
+ else if (parent == dupliObParent) {
+ if (dupliObParent->parent == NULL) {
+ createTransformWriter(parent, NULL, NULL);
+ }
+ else {
+ createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent);
+ }
+ }
else {
createTransformWriter(parent, dupliObParent, dupliObParent);
}
@@ -445,44 +454,42 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
{
- Base *base = static_cast<Base *>(m_scene->base.first);
-
- while (base) {
- Object *ob = base->object;
- exploreObject(eval_ctx, ob, NULL);
-
- base = base->next;
+ for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
+ exploreObject(eval_ctx, base, NULL);
}
}
-void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent)
+void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent)
{
+ Object *ob = ob_base->object;
ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
- createShapeWriter(ob, dupliObParent);
+ createShapeWriter(ob_base, dupliObParent);
if (lb) {
- DupliObject *dupliob = static_cast<DupliObject *>(lb->first);
+ Base fake_base = *ob_base; // copy flags (like selection state) from the real object.
+ fake_base.next = fake_base.prev = NULL;
- while (dupliob) {
+ for (DupliObject *dupliob = static_cast<DupliObject *>(lb->first); dupliob; dupliob = dupliob->next) {
if (dupliob->type == OB_DUPLIGROUP) {
- exploreObject(eval_ctx, dupliob->ob, ob);
+ fake_base.object = dupliob->ob;
+ exploreObject(eval_ctx, &fake_base, ob);
}
-
- dupliob = dupliob->next;
}
}
free_object_duplilist(lb);
}
-void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
+void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
{
+ Object *ob = ob_base->object;
+
if (!object_is_shape(ob)) {
return;
}
- if (!export_object(&m_settings, ob)) {
+ if (!export_object(&m_settings, ob_base)) {
return;
}
diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h
index b0eb8e185d6..80fee067c04 100644
--- a/source/blender/alembic/intern/abc_exporter.h
+++ b/source/blender/alembic/intern/abc_exporter.h
@@ -36,11 +36,14 @@ struct EvaluationContext;
struct Main;
struct Object;
struct Scene;
+struct SceneLayer;
+struct Base;
struct ExportSettings {
ExportSettings();
Scene *scene;
+ SceneLayer *sl; // Scene layer to export; all its objects will be exported, unless selected_only=true
bool selected_only;
bool visible_layers_only;
@@ -105,10 +108,10 @@ private:
void createTransformWritersHierarchy(EvaluationContext *eval_ctx);
void createTransformWritersFlat();
void createTransformWriter(Object *ob, Object *parent, Object *dupliObParent);
- void exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent = NULL);
- void exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent);
+ void exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent);
+ void exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent);
void createShapeWriters(EvaluationContext *eval_ctx);
- void createShapeWriter(Object *ob, Object *dupliObParent);
+ void createShapeWriter(Base *ob_base, Object *dupliObParent);
AbcTransformWriter *getXForm(const std::string &name);
diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc
index 14bcf6731ea..e328df24e53 100644
--- a/source/blender/alembic/intern/abc_hair.cc
+++ b/source/blender/alembic/intern/abc_hair.cc
@@ -77,7 +77,6 @@ void AbcHairWriter::do_write()
DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH);
DM_ensure_tessface(dm);
- DM_update_tessface_data(dm);
std::vector<Imath::V3f> verts;
std::vector<int32_t> hvertices;
@@ -164,7 +163,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL, NULL);
- copy_zup_yup(tmp_nor.getValue(), normal);
+ copy_yup_from_zup(tmp_nor.getValue(), normal);
norm_values.push_back(tmp_nor);
}
}
@@ -198,7 +197,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
MVert *mv = mverts + vtx[o];
normal_short_to_float_v3(normal, mv->no);
- copy_zup_yup(tmp_nor.getValue(), normal);
+ copy_yup_from_zup(tmp_nor.getValue(), normal);
norm_values.push_back(tmp_nor);
found = true;
break;
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index bdd75f93189..8bc9c335054 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -112,7 +112,7 @@ static void get_vertices(DerivedMesh *dm, std::vector<Imath::V3f> &points)
MVert *verts = dm->getVertArray(dm);
for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) {
- copy_zup_yup(points[i].getValue(), verts[i].co);
+ copy_yup_from_zup(points[i].getValue(), verts[i].co);
}
}
@@ -182,7 +182,7 @@ static void get_vertex_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals
for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) {
normal_short_to_float_v3(no, verts[i].no);
- copy_zup_yup(normals[i].getValue(), no);
+ copy_yup_from_zup(normals[i].getValue(), no);
}
}
@@ -211,7 +211,7 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals)
for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
const int index = ml->v;
- copy_zup_yup(normals[loop_index].getValue(), lnors[index]);
+ copy_yup_from_zup(normals[loop_index].getValue(), lnors[index]);
}
}
}
@@ -226,14 +226,14 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals)
BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no);
for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
- copy_zup_yup(normals[loop_index].getValue(), no);
+ copy_yup_from_zup(normals[loop_index].getValue(), no);
}
}
else {
/* Smooth shaded, use individual vert normals. */
for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
normal_short_to_float_v3(no, verts[ml->v].no);
- copy_zup_yup(normals[loop_index].getValue(), no);
+ copy_yup_from_zup(normals[loop_index].getValue(), no);
}
}
}
@@ -590,7 +590,7 @@ void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels
float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities);
for (int i = 0; i < totverts; ++i) {
- copy_zup_yup(vels[i].getValue(), mesh_vels);
+ copy_yup_from_zup(vels[i].getValue(), mesh_vels);
mesh_vels += 3;
}
}
@@ -726,7 +726,7 @@ static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions
const Imath::V3f &ceil_pos = (*ceil_positions)[i];
interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight);
- copy_yup_zup(mvert.co, tmp);
+ copy_zup_from_yup(mvert.co, tmp);
mvert.bweight = 0;
}
@@ -755,7 +755,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr
MVert &mvert = mverts[i];
Imath::V3f pos_in = (*positions)[i];
- copy_yup_zup(mvert.co, pos_in.getValue());
+ copy_zup_from_yup(mvert.co, pos_in.getValue());
mvert.bweight = 0;
@@ -765,7 +765,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr
short no[3];
normal_float_to_short_v3(no, nor_in.getValue());
- copy_yup_zup(mvert.no, no);
+ copy_zup_from_yup(mvert.no, no);
}
}
}
diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc
index 4f57dfdae9e..d0b9561f679 100644
--- a/source/blender/alembic/intern/abc_nurbs.cc
+++ b/source/blender/alembic/intern/abc_nurbs.cc
@@ -153,7 +153,7 @@ void AbcNurbsWriter::do_write()
const BPoint *bp = nu->bp;
for (int i = 0; i < size; ++i, ++bp) {
- copy_zup_yup(positions[i].getValue(), bp->vec);
+ copy_yup_from_zup(positions[i].getValue(), bp->vec);
weights[i] = bp->vec[3];
}
@@ -281,7 +281,7 @@ void AbcNurbsReader::readObjectData(Main *bmain, float time)
posw_in = (*weights)[i];
}
- copy_yup_zup(bp->vec, pos_in.getValue());
+ copy_zup_from_yup(bp->vec, pos_in.getValue());
bp->vec[3] = posw_in;
bp->f1 = SELECT;
bp->radius = 1.0f;
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 9dfccdb8c7f..a5b8af542fc 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -97,14 +97,14 @@ Imath::Box3d AbcObjectWriter::bounds()
return Imath::Box3d();
}
- /* Convert Z-up to Y-up. */
+ /* Convert Z-up to Y-up. This also changes which vector goes into which min/max property. */
this->m_bounds.min.x = bb->vec[0][0];
this->m_bounds.min.y = bb->vec[0][2];
- this->m_bounds.min.z = -bb->vec[0][1];
+ this->m_bounds.min.z = -bb->vec[6][1];
this->m_bounds.max.x = bb->vec[6][0];
this->m_bounds.max.y = bb->vec[6][2];
- this->m_bounds.max.z = -bb->vec[6][1];
+ this->m_bounds.max.z = -bb->vec[0][1];
return this->m_bounds;
}
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index f8ce72d845d..bb375eb9561 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -35,6 +35,7 @@
extern "C" {
#include "DNA_object_types.h"
+#include "DNA_layer_types.h"
#include "BLI_math.h"
}
@@ -58,6 +59,16 @@ std::string get_id_name(ID *id)
return name;
}
+
+/**
+ * @brief get_object_dag_path_name returns the name under which the object
+ * will be exported in the Alembic file. It is of the form
+ * "[../grandparent/]parent/object" if dupli_parent is NULL, or
+ * "dupli_parent/[../grandparent/]parent/object" otherwise.
+ * @param ob
+ * @param dupli_parent
+ * @return
+ */
std::string get_object_dag_path_name(Object *ob, Object *dupli_parent)
{
std::string name = get_id_name(ob);
@@ -76,31 +87,9 @@ std::string get_object_dag_path_name(Object *ob, Object *dupli_parent)
return name;
}
-bool object_selected(Object *ob)
+bool object_selected(const Base * const ob_base)
{
- return ob->flag & SELECT;
-}
-
-bool parent_selected(Object *ob)
-{
- if (object_selected(ob)) {
- return true;
- }
-
- bool do_export = false;
-
- Object *parent = ob->parent;
-
- while (parent != NULL) {
- if (object_selected(parent)) {
- do_export = true;
- break;
- }
-
- parent = parent->parent;
- }
-
- return do_export;
+ return ob_base->flag & SELECT;
}
Imath::M44d convert_matrix(float mat[4][4])
@@ -197,7 +186,7 @@ void create_transform_matrix(float r_mat[4][4])
copy_m4_m3(transform_mat, rot_mat);
/* Add translation to transformation matrix. */
- copy_yup_zup(transform_mat[3], loc);
+ copy_zup_from_yup(transform_mat[3], loc);
/* Create scale matrix. */
scale_mat[0][0] = scale[0];
@@ -417,7 +406,7 @@ void create_transform_matrix(Object *obj, float transform_mat[4][4])
copy_m4_m3(transform_mat, rot_mat);
/* Add translation to transformation matrix. */
- copy_zup_yup(transform_mat[3], loc);
+ copy_yup_from_zup(transform_mat[3], loc);
/* Create scale matrix. */
scale_mat[0][0] = scale[0];
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 60a96855d14..328f2c41a87 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -43,13 +43,13 @@ struct ImportSettings;
struct ID;
struct Object;
+struct Base;
std::string get_id_name(ID *id);
std::string get_id_name(Object *ob);
std::string get_object_dag_path_name(Object *ob, Object *dupli_parent);
-bool object_selected(Object *ob);
-bool parent_selected(Object *ob);
+bool object_selected(const Base * const ob_base);
Imath::M44d convert_matrix(float mat[4][4]);
void create_transform_matrix(float r_mat[4][4]);
@@ -116,14 +116,14 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe
/* Copy from Y-up to Z-up. */
-ABC_INLINE void copy_yup_zup(float zup[3], const float yup[3])
+ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
{
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = yup[1];
}
-ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3])
+ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
{
zup[0] = yup[0];
zup[1] = -yup[2];
@@ -132,14 +132,14 @@ ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3])
/* Copy from Z-up to Y-up. */
-ABC_INLINE void copy_zup_yup(float yup[3], const float zup[3])
+ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
{
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -zup[1];
}
-ABC_INLINE void copy_zup_yup(short yup[3], const short zup[3])
+ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
{
yup[0] = zup[0];
yup[1] = zup[2];
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index d8d017119b1..fcfe634924f 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -332,21 +332,37 @@ void ABC_export(
BLI_strncpy(job->filename, filepath, 1024);
job->settings.scene = job->scene;
+
+ /* Sybren: for now we only export the active scene layer.
+ * Later in the 2.8 development process this may be replaced by using
+ * a specific collection for Alembic I/O, which can then be toggled
+ * between "real" objects and cached Alembic files. */
+ job->settings.sl = CTX_data_scene_layer(C);
+
job->settings.frame_start = params->frame_start;
job->settings.frame_end = params->frame_end;
job->settings.frame_step_xform = params->frame_step_xform;
job->settings.frame_step_shape = params->frame_step_shape;
job->settings.shutter_open = params->shutter_open;
job->settings.shutter_close = params->shutter_close;
+
+ /* Sybren: For now this is ignored, until we can get selection
+ * detection working through Base pointers (instead of ob->flags). */
job->settings.selected_only = params->selected_only;
+
job->settings.export_face_sets = params->face_sets;
job->settings.export_normals = params->normals;
job->settings.export_uvs = params->uvs;
job->settings.export_vcols = params->vcolors;
job->settings.apply_subdiv = params->apply_subdiv;
job->settings.flatten_hierarchy = params->flatten_hierarchy;
+
+ /* Sybren: visible_layer & renderable only is ignored for now,
+ * to be replaced with collections later in the 2.8 dev process
+ * (also see note above). */
job->settings.visible_layers_only = params->visible_layers_only;
job->settings.renderable_only = params->renderable_only;
+
job->settings.use_subdiv_schema = params->use_subdiv_schema;
job->settings.export_ogawa = (params->compression_type == ABC_ARCHIVE_OGAWA);
job->settings.pack_uv = params->packuv;
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 3da0434687c..1b967f889c0 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -45,6 +45,7 @@ int BLF_init(int points, int dpi);
void BLF_exit(void);
void BLF_default_dpi(int dpi);
void BLF_default_set(int fontid);
+int BLF_default(void); /* get default font ID so we can pass it to other functions */
void BLF_cache_clear(void);
@@ -64,6 +65,17 @@ void BLF_aspect(int fontid, float x, float y, float z);
void BLF_position(int fontid, float x, float y, float z);
void BLF_size(int fontid, int size, int dpi);
+/* goal: small but useful color API */
+void BLF_color4ubv(int fontid, const unsigned char rgba[4]);
+void BLF_color3ubv(int fontid, const unsigned char rgb[3]);
+void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha);
+void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b);
+void BLF_color4f(int fontid, float r, float g, float b, float a);
+void BLF_color4fv(int fontid, const float rgba[4]);
+void BLF_color3f(int fontid, float r, float g, float b);
+void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha);
+/* also available: UI_FontThemeColor(fontid, colorid) */
+
/* Set a 4x4 matrix to be multiplied before draw the text.
* Remember that you need call BLF_enable(BLF_MATRIX)
* to enable this.
@@ -125,27 +137,11 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt
*/
float BLF_fixed_width(int fontid) ATTR_WARN_UNUSED_RESULT;
-/* and this two function return the width and height
- * of the string, using the default font and both value
- * are multiplied by the aspect of the font.
- */
-void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height) ATTR_NONNULL();
-float BLF_width_default(const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BLF_height_default(const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-/* Set rotation for default font. */
-void BLF_rotation_default(float angle);
-
-/* Enable/disable options to the default font. */
-void BLF_enable_default(int option);
-void BLF_disable_default(int option);
-
/* By default, rotation and clipping are disable and
* have to be enable/disable using BLF_enable/disable.
*/
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
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 1ce4753cc39..ab7c831f95c 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -50,7 +50,6 @@
#include "BLI_math.h"
#include "BLI_threads.h"
-#include "BIF_gl.h"
#include "BLF_api.h"
#include "IMB_colormanagement.h"
@@ -176,6 +175,12 @@ void BLF_default_set(int fontid)
}
}
+int BLF_default(void)
+{
+ ASSERT_DEFAULT_SET;
+ return global_font_default;
+}
+
int BLF_load(const char *name)
{
FontBLF *font;
@@ -359,24 +364,6 @@ void BLF_disable(int fontid, int option)
}
}
-void BLF_enable_default(int option)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->flags |= option;
- }
-}
-
-void BLF_disable_default(int option)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->flags &= ~option;
- }
-}
-
void BLF_aspect(int fontid, float x, float y, float z)
{
FontBLF *font = blf_get(fontid);
@@ -466,6 +453,76 @@ void BLF_blur(int fontid, int size)
}
#endif
+void BLF_color4ubv(int fontid, const unsigned char rgba[4])
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->color[0] = rgba[0];
+ font->color[1] = rgba[1];
+ font->color[2] = rgba[2];
+ font->color[3] = rgba[3];
+ }
+}
+
+void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha)
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->color[0] = rgb[0];
+ font->color[1] = rgb[1];
+ font->color[2] = rgb[2];
+ font->color[3] = alpha;
+ }
+}
+
+void BLF_color3ubv(int fontid, const unsigned char rgb[3])
+{
+ BLF_color3ubv_alpha(fontid, rgb, 255);
+}
+
+void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b)
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->color[0] = r;
+ font->color[1] = g;
+ font->color[2] = b;
+ font->color[3] = 255;
+ }
+}
+
+void BLF_color4fv(int fontid, const float rgba[4])
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ rgba_float_to_uchar(font->color, rgba);
+ }
+}
+
+void BLF_color4f(int fontid, float r, float g, float b, float a)
+{
+ float rgba[4] = { r, g, b, a };
+ BLF_color4fv(fontid, rgba);
+}
+
+void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha)
+{
+ float rgba[4];
+ copy_v3_v3(rgba, rgb);
+ rgba[3] = alpha;
+ BLF_color4fv(fontid, rgba);
+}
+
+void BLF_color3f(int fontid, float r, float g, float b)
+{
+ float rgba[4] = { r, g, b, 1.0f };
+ BLF_color4fv(fontid, rgba);
+}
+
void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
{
ASSERT_DEFAULT_SET;
@@ -485,15 +542,6 @@ void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t l
BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
}
-void BLF_rotation_default(float angle)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->angle = angle;
- }
-}
-
static void blf_draw_gl__start(FontBLF *font)
{
/*
@@ -517,10 +565,6 @@ static void blf_draw_gl__start(FontBLF *font)
if (font->flags & BLF_ROTATION) /* radians -> degrees */
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);
@@ -698,14 +742,6 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt
}
}
-void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height)
-{
- ASSERT_DEFAULT_SET;
-
- BLF_size(global_font_default, global_font_points, global_font_dpi);
- BLF_width_and_height(global_font_default, str, len, r_width, r_height);
-}
-
float BLF_width_ex(
int fontid, const char *str, size_t len,
struct ResultBLF *r_info)
@@ -736,14 +772,6 @@ float BLF_fixed_width(int fontid)
return 0.0f;
}
-float BLF_width_default(const char *str, size_t len)
-{
- ASSERT_DEFAULT_SET;
-
- BLF_size(global_font_default, global_font_points, global_font_dpi);
- return BLF_width(global_font_default, str, len);
-}
-
float BLF_height_ex(
int fontid, const char *str, size_t len,
struct ResultBLF *r_info)
@@ -807,15 +835,6 @@ float BLF_ascender(int fontid)
return 0.0f;
}
-float BLF_height_default(const char *str, size_t len)
-{
- ASSERT_DEFAULT_SET;
-
- BLF_size(global_font_default, global_font_points, global_font_dpi);
-
- return BLF_height(global_font_default, str, len);
-}
-
void BLF_rotation(int fontid, float angle)
{
FontBLF *font = blf_get(fontid);
@@ -837,18 +856,6 @@ 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)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->clip_rec.xmin = xmin;
- font->clip_rec.ymin = ymin;
- font->clip_rec.xmax = xmax;
- font->clip_rec.ymax = ymax;
- }
-}
-
void BLF_wordwrap(int fontid, int wrap_width)
{
FontBLF *font = blf_get(fontid);
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 71350a0f8dc..d0293eccf3a 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -933,8 +933,6 @@ void blf_font_free(FontBLF *font)
static void blf_font_fill(FontBLF *font)
{
- unsigned int i;
-
font->aspect[0] = 1.0f;
font->aspect[1] = 1.0f;
font->aspect[2] = 1.0f;
@@ -942,9 +940,15 @@ static void blf_font_fill(FontBLF *font)
font->pos[1] = 0.0f;
font->angle = 0.0f;
- for (i = 0; i < 16; i++)
+ for (int i = 0; i < 16; i++)
font->m[i] = 0;
+ /* annoying bright color so we can see where to add BLF_color calls */
+ font->color[0] = 255;
+ font->color[1] = 255;
+ font->color[2] = 0;
+ font->color[3] = 255;
+
font->clip_rec.xmin = 0.0f;
font->clip_rec.xmax = 0.0f;
font->clip_rec.ymin = 0.0f;
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 07db2217bac..bf45a27e51c 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -133,6 +133,12 @@ BVHTree *bvhtree_from_editmesh_edges_ex(
BVHTree *bvhtree_from_mesh_edges(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh,
float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_edges_ex(
+ struct BVHTreeFromMesh *data,
+ struct MVert *vert, const bool vert_allocated,
+ struct MEdge *edge, const int edges_num, const bool edge_allocated,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_faces(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon,
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index 9948f21ba90..4876461bfe0 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -79,6 +79,7 @@ DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispba
*/
struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
struct DerivedMesh *CDDM_copy_from_tessface(struct DerivedMesh *dm);
+struct DerivedMesh *CDDM_copy_with_tessface(struct DerivedMesh *dm);
/* creates a CDDerivedMesh with the same layer stack configuration as the
* given DerivedMesh and containing the requested numbers of elements.
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
new file mode 100644
index 00000000000..90904cdfddd
--- /dev/null
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -0,0 +1,91 @@
+/*
+ * ***** 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): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_COLLECTION_H__
+#define __BKE_COLLECTION_H__
+
+/** \file blender/blenkernel/BKE_collection.h
+ * \ingroup bke
+ */
+
+#include "BLI_ghash.h"
+#include "BLI_iterator.h"
+#include "DNA_listBase.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Iterator;
+struct SceneCollection;
+struct Object;
+struct Base;
+struct Main;
+struct Scene;
+
+struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name);
+bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc);
+struct SceneCollection *BKE_collection_master(struct Scene *scene);
+void BKE_collection_master_free(struct Scene *scene);
+void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
+void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
+void BKE_collection_object_remove(struct Main *bmain, struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us);
+void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us);
+
+typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
+typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
+
+void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data);
+void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data);
+
+/* iterators */
+void BKE_scene_collections_Iterator_begin(struct Iterator *iter, void *data_in);
+void BKE_scene_collections_Iterator_next(struct Iterator *iter);
+void BKE_scene_collections_Iterator_end(struct Iterator *iter);
+
+void BKE_scene_objects_Iterator_begin(struct Iterator *iter, void *data_in);
+void BKE_scene_objects_Iterator_next(struct Iterator *iter);
+void BKE_scene_objects_Iterator_end(struct Iterator *iter);
+
+#define FOREACH_SCENE_COLLECTION(scene, _sc) \
+ ITER_BEGIN(BKE_scene_collections_Iterator_begin, \
+ BKE_scene_collections_Iterator_next, \
+ BKE_scene_collections_Iterator_end, \
+ scene, SceneCollection, _sc)
+
+#define FOREACH_SCENE_COLLECTION_END \
+ ITER_END
+
+#define FOREACH_SCENE_OBJECT(scene, _ob) \
+ ITER_BEGIN(BKE_scene_objects_Iterator_begin, \
+ BKE_scene_objects_Iterator_next, \
+ BKE_scene_objects_Iterator_end, \
+ scene, Object, _ob)
+
+#define FOREACH_SCENE_OBJECT_END \
+ ITER_END
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_COLLECTION_H__ */
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 4da6a61cbfa..23f9ff28f8b 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -40,12 +40,16 @@ extern "C" {
struct ARegion;
struct bScreen;
struct CacheFile;
+struct LayerCollection;
struct ListBase;
struct Main;
struct Object;
+struct Base;
struct PointerRNA;
struct ReportList;
struct Scene;
+struct SceneCollection;
+struct SceneLayer;
struct ScrArea;
struct SpaceLink;
struct View3D;
@@ -166,6 +170,7 @@ struct SpaceAction *CTX_wm_space_action(const bContext *C);
struct SpaceInfo *CTX_wm_space_info(const bContext *C);
struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C);
struct SpaceClip *CTX_wm_space_clip(const bContext *C);
+struct SpaceCollections *CTX_wm_space_collections(const bContext *C);
void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm);
void CTX_wm_window_set(bContext *C, struct wmWindow *win);
@@ -239,6 +244,9 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
+struct LayerCollection *CTX_data_layer_collection(const bContext *C);
+struct SceneCollection *CTX_data_scene_collection(const bContext *C);
+struct SceneLayer *CTX_data_scene_layer(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
const char *CTX_data_mode_string(const bContext *C);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 09a069ee36f..f718e9c8555 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -33,6 +33,7 @@
* \author nzc
*/
+struct BaseLegacy;
struct Base;
struct EvaluationContext;
struct Group;
@@ -44,8 +45,8 @@ void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
-bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
-bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
+bool BKE_group_object_add(struct Group *group, struct Object *ob);
+bool BKE_group_object_unlink(struct Group *group, struct Object *ob);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
bool BKE_group_object_exists(struct Group *group, struct Object *ob);
bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
new file mode 100644
index 00000000000..9bee353bb3a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -0,0 +1,221 @@
+/*
+ * ***** 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): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LAYER_H__
+#define __BKE_LAYER_H__
+
+/** \file blender/blenkernel/BKE_layer.h
+ * \ingroup bke
+ */
+
+#include "BKE_collection.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TODO_LAYER_SYNC /* syncing of SceneCollection and LayerCollection trees*/
+#define TODO_LAYER_SYNC_FILTER /* syncing of filter_objects across all trees */
+#define TODO_LAYER_OVERRIDE /* CollectionOverride */
+#define TODO_LAYER_CONTEXT /* get/set current (context) SceneLayer */
+#define TODO_LAYER_BASE /* BaseLegacy to Base related TODO */
+#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
+#define TODO_LAYER_DEPSGRAPH /* placeholder for real Depsgraph fix */
+#define TODO_LAYER /* generic todo */
+
+struct CollectionEngineSettings;
+struct LayerCollection;
+struct ID;
+struct ListBase;
+struct Main;
+struct Object;
+struct Base;
+struct RenderEngine;
+struct Scene;
+struct SceneCollection;
+struct SceneLayer;
+
+struct SceneLayer *BKE_scene_layer_active(struct Scene *scene);
+struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name);
+
+bool BKE_scene_layer_remove(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl);
+
+void BKE_scene_layer_free(struct SceneLayer *sl);
+
+void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine);
+
+void BKE_scene_layer_selected_objects_tag(struct SceneLayer *sl, const int tag);
+
+struct SceneLayer *BKE_scene_layer_find_from_collection(struct Scene *scene, struct LayerCollection *lc);
+struct Base *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob);
+void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
+void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase);
+void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
+
+void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl);
+void BKE_scene_layer_engine_settings_object_recalculate(struct SceneLayer *sl, struct Object *ob);
+void BKE_scene_layer_engine_settings_collection_recalculate(struct SceneLayer *sl, struct LayerCollection *lc);
+void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl, const char *engine_name);
+
+void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl);
+
+int BKE_layer_collection_count(struct SceneLayer *sl);
+
+int BKE_layer_collection_findindex(struct SceneLayer *sl, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneCollection *sc);
+
+void BKE_collection_unlink(struct SceneLayer *sl, struct LayerCollection *lc);
+
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc);
+bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
+
+/* syncing */
+
+void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
+void BKE_layer_sync_object_link(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+
+/* override */
+
+void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id);
+
+/* engine settings */
+typedef void (*CollectionEngineSettingsCB)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
+struct CollectionEngineSettings *BKE_layer_collection_engine_get(struct LayerCollection *lc, const char *engine_name);
+void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, CollectionEngineSettingsCB func);
+void BKE_layer_collection_engine_settings_callback_free(void);
+
+struct CollectionEngineSettings *BKE_layer_collection_engine_settings_create(const char *engine_name);
+void BKE_layer_collection_engine_settings_free(struct CollectionEngineSettings *ces);
+
+void BKE_collection_engine_property_add_float(struct CollectionEngineSettings *ces, const char *name, float value);
+void BKE_collection_engine_property_add_int(struct CollectionEngineSettings *ces, const char *name, int value);
+struct CollectionEngineProperty *BKE_collection_engine_property_get(struct CollectionEngineSettings *ces, const char *name);
+int BKE_collection_engine_property_value_get_int(struct CollectionEngineSettings *ces, const char *name);
+float BKE_collection_engine_property_value_get_float(struct CollectionEngineSettings *ces, const char *name);
+void BKE_collection_engine_property_value_set_int(struct CollectionEngineSettings *ces, const char *name, int value);
+void BKE_collection_engine_property_value_set_float(struct CollectionEngineSettings *ces, const char *name, float value);
+bool BKE_collection_engine_property_use_get(struct CollectionEngineSettings *ces, const char *name);
+void BKE_collection_engine_property_use_set(struct CollectionEngineSettings *ces, const char *name, bool value);
+
+/* iterators */
+
+void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_selected_objects_Iterator_next(Iterator *iter);
+void BKE_selected_objects_Iterator_end(Iterator *iter);
+
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_objects_Iterator_next(Iterator *iter);
+void BKE_visible_objects_Iterator_end(Iterator *iter);
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_bases_Iterator_next(Iterator *iter);
+void BKE_visible_bases_Iterator_end(Iterator *iter);
+
+#define FOREACH_SELECTED_OBJECT(sl, _ob) \
+ ITER_BEGIN(BKE_selected_objects_Iterator_begin, \
+ BKE_selected_objects_Iterator_next, \
+ BKE_selected_objects_Iterator_end, \
+ sl, Object, _ob)
+
+#define FOREACH_SELECTED_OBJECT_END \
+ ITER_END
+
+#define FOREACH_VISIBLE_OBJECT(sl, _ob) \
+ ITER_BEGIN(BKE_visible_objects_Iterator_begin, \
+ BKE_visible_objects_Iterator_next, \
+ BKE_visible_objects_Iterator_end, \
+ sl, Object, _ob)
+
+#define FOREACH_VISIBLE_OBJECT_END \
+ ITER_END
+
+
+#define FOREACH_VISIBLE_BASE(sl, _object_base) \
+ ITER_BEGIN(BKE_visible_bases_Iterator_begin, \
+ BKE_visible_bases_Iterator_next, \
+ BKE_visible_bases_Iterator_end, \
+ sl, Base, _object_base)
+
+#define FOREACH_VISIBLE_BASE_END \
+ ITER_END
+
+
+#define FOREACH_OBJECT(sl, _ob) \
+{ \
+ Base *base; \
+ for (base = sl->object_bases.first; base; base = base->next) { \
+ _ob = base->object;
+
+#define FOREACH_OBJECT_END \
+ } \
+}
+
+#define FOREACH_OBJECT_FLAG(scene, sl, flag, _ob) \
+{ \
+ IteratorBeginCb func_begin; \
+ IteratorCb func_next, func_end; \
+ void *data_in; \
+ \
+ if (flag == SELECT) { \
+ func_begin = &BKE_selected_objects_Iterator_begin; \
+ func_next = &BKE_selected_objects_Iterator_next; \
+ func_end = &BKE_selected_objects_Iterator_end; \
+ data_in = sl; \
+ } \
+ else { \
+ func_begin = BKE_scene_objects_Iterator_begin; \
+ func_next = BKE_scene_objects_Iterator_next; \
+ func_end = BKE_scene_objects_Iterator_end; \
+ data_in = scene; \
+ } \
+ ITER_BEGIN(func_begin, func_next, func_end, data_in, Object, _ob)
+
+
+#define FOREACH_OBJECT_FLAG_END \
+ ITER_END \
+}
+
+/* temporary hacky solution waiting for final depsgraph evaluation */
+#define DEG_OBJECT_ITER(sl_, engine_name_, ob_) \
+{ \
+ /* temporary solution, waiting for depsgraph update */ \
+ BKE_scene_layer_engine_settings_update(sl, engine_name_); \
+ \
+ /* flush all the data to objects*/ \
+ Base *base_; \
+ for (base_ = sl->object_bases.first; base_; base_ = base_->next) { \
+ ob_ = base_->object; \
+ ob_->base_flag = base_->flag;
+
+#define DEG_OBJECT_ITER_END \
+ } \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_LAYER_H__ */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 2d9c35f7fd0..72ae2cf4efa 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -86,7 +86,7 @@ bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const boo
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
-void BKE_id_expand_local(struct ID *id);
+void BKE_id_expand_local(struct Main *bmain, struct ID *id);
void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id);
bool new_id(struct ListBase *lb, struct ID *id, const char *name);
@@ -105,6 +105,9 @@ void BKE_main_free(struct Main *mainvar);
void BKE_main_lock(struct Main *bmain);
void BKE_main_unlock(struct Main *bmain);
+void BKE_main_relations_create(struct Main *bmain);
+void BKE_main_relations_free(struct Main *bmain);
+
struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img);
struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data);
void BKE_main_thumbnail_create(struct Main *bmain);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index a7470107c24..1258e2fa72e 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -36,25 +36,28 @@ struct Main;
/* Tips for the callback for cases it's gonna to modify the pointer. */
enum {
- IDWALK_NOP = 0,
- IDWALK_NEVER_NULL = (1 << 0),
- IDWALK_NEVER_SELF = (1 << 1),
+ IDWALK_CB_NOP = 0,
+ IDWALK_CB_NEVER_NULL = (1 << 0),
+ IDWALK_CB_NEVER_SELF = (1 << 1),
/**
* Indicates whether this is direct (i.e. by local data) or indirect (i.e. by linked data) usage.
* \note Object proxies are half-local, half-linked...
*/
- IDWALK_INDIRECT_USAGE = (1 << 2),
+ IDWALK_CB_INDIRECT_USAGE = (1 << 2),
+
+ /** That ID is used as mere sub-data by its owner
+ * (only case currently: those f***ing nodetrees in materials etc.).
+ * This means callback shall not *do* anything, only use this as informative data if it needs it. */
+ IDWALK_CB_PRIVATE = (1 << 3),
/**
* Adjusts #ID.us reference-count.
* \note keep in sync with 'newlibadr_us' use in readfile.c
*/
- IDWALK_USER = (1 << 8),
- /**
- * Ensure #ID.us is at least 1 on use.
- */
- IDWALK_USER_ONE = (1 << 9),
+ IDWALK_CB_USER = (1 << 8),
+ /** Ensure #ID.us is at least 1 on use. */
+ IDWALK_CB_USER_ONE = (1 << 9),
};
enum {
@@ -68,17 +71,19 @@ enum {
*
* \return a set of flags to control further iteration (0 to keep going).
*/
-typedef int (*LibraryIDLinkCallback) (void *user_data, struct ID *id_self, struct ID **id_pointer, int cd_flag);
+typedef int (*LibraryIDLinkCallback) (void *user_data, struct ID *id_self, struct ID **id_pointer, int cb_flag);
/* Flags for the foreach function itself. */
enum {
+ IDWALK_NOP = 0,
IDWALK_READONLY = (1 << 0),
IDWALK_RECURSE = (1 << 1), /* Also implies IDWALK_READONLY. */
};
/* Loop over all of the ID's this datablock links to. */
-void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
-void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cd_flag);
+void BKE_library_foreach_ID_link(
+ struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
+void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cb_flag);
int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index a4f5c425282..387045878f3 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -51,6 +51,8 @@ extern "C" {
struct EvaluationContext;
struct Library;
struct MainLock;
+struct GHash;
+struct BLI_mempool;
/* Blender thumbnail, as written on file (width, height, and data as char RGBA). */
/* We pack pixel data after that struct. */
@@ -59,6 +61,22 @@ typedef struct BlendThumbnail {
char rect[0];
} BlendThumbnail;
+/* Structs caching relations between data-blocks in a given Main. */
+typedef struct MainIDRelationsEntry {
+ struct MainIDRelationsEntry *next;
+ /* WARNING! for user_to_used, that pointer is really an ID** one, but for used_to_user, it’s only an ID* one! */
+ struct ID **id_pointer;
+ int usage_flag; /* Using IDWALK_ enums, in BKE_library_query.h */
+} MainIDRelationsEntry;
+
+typedef struct MainIDRelations {
+ struct GHash *id_user_to_used;
+ struct GHash *id_used_to_user;
+
+ /* Private... */
+ struct BLI_mempool *entry_pool;
+} MainIDRelations;
+
typedef struct Main {
struct Main *next, *prev;
char name[1024]; /* 1024 = FILE_MAX */
@@ -111,6 +129,11 @@ typedef struct Main {
/* Evaluation context used by viewport */
struct EvaluationContext *eval_ctx;
+ /* Must be generated, used and freed by same code - never assume this is valid data unless you know
+ * when, who and how it was created.
+ * Used by code doing a lot of remapping etc. at once to speed things up. */
+ struct MainIDRelations *relations;
+
struct MainLock *lock;
} Main;
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 92b186d7329..7a522cba282 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -106,8 +106,8 @@ typedef enum {
} ModifierTypeFlag;
/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
-typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cd_flag);
-typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cd_flag);
+typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cb_flag);
+typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag);
typedef void (*TexWalkFunc)(void *userData, struct Object *ob, struct ModifierData *md, const char *propname);
typedef enum ModifierApplyFlag {
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 546f0d97c2b..67f7fa5e029 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -687,6 +687,13 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Tree
+ */
+
+void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index);
+
/* -------------------------------------------------------------------- */
/** \name Shader Nodes
*/
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 3f1c6bae75c..4dd9e01ba32 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -35,12 +35,13 @@ extern "C" {
#include "BLI_compiler_attrs.h"
-struct Base;
+struct BaseLegacy;
struct EvaluationContext;
struct Scene;
struct Object;
struct BoundBox;
struct View3D;
+struct SceneLayer;
struct SoftBody;
struct BulletSoftBody;
struct MovieClip;
@@ -89,9 +90,9 @@ struct Object *BKE_object_add_only_object(
int type, const char *name)
ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
struct Object *BKE_object_add(
- struct Main *bmain, struct Scene *scene,
+ struct Main *bmain, struct Scene *scene, struct SceneLayer *sl,
int type, const char *name)
- ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+ ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL;
void *BKE_object_obdata_add_from_type(
struct Main *bmain,
int type, const char *name)
@@ -136,14 +137,9 @@ void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float
/* possibly belong in own moduke? */
struct BoundBox *BKE_boundbox_alloc_unit(void);
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3]);
-bool BKE_boundbox_ray_hit_check(
- const struct BoundBox *bb,
- const float ray_start[3], const float ray_normal[3],
- float *r_lambda);
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]);
-void BKE_boundbox_scale(struct BoundBox *bb_dst, const struct BoundBox *bb_src, float scale);
struct BoundBox *BKE_boundbox_ensure_minimum_dimensions(
struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon);
@@ -260,7 +256,7 @@ typedef enum eObjectSet {
struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
struct LinkNode *BKE_object_groups(struct Object *ob);
-void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
+void BKE_object_groups_clear(struct Object *object);
struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index b3e3968ca9b..e5967be0bc7 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -384,7 +384,7 @@ void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleDa
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);
+typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cb_flag);
void BKE_particlesystem_id_loop(struct ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 965a97f08ba..443c3b2b5b2 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -53,7 +53,7 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
/* Callback format for performing operations on ID-pointers for rigidbody world. */
-typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cd_flag);
+typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag);
void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata);
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index a504f1bac3d..1579a0c7bb3 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -77,9 +77,9 @@ void sca_move_controller(struct bController *cont_to_move, struct Object *ob, in
void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up);
/* Callback format for performing operations on ID-pointers for sensors/controllers/actuators. */
-typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cd_flag);
-typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cd_flag);
-typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cd_flag);
+typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cb_flag);
+typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cb_flag);
+typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cb_flag);
void BKE_sca_sensors_id_loop(struct ListBase *senslist, SCASensorIDFunc func, void *userdata);
void BKE_sca_controllers_id_loop(struct ListBase *contlist, SCAControllerIDFunc func, void *userdata);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index d2152950bff..181d4b12703 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -38,14 +38,16 @@ extern "C" {
#endif
struct AviCodecData;
-struct Base;
+struct BaseLegacy;
struct EvaluationContext;
struct Main;
struct Object;
+struct Base;
struct QuicktimeCodecData;
struct RenderData;
struct SceneRenderLayer;
struct Scene;
+struct SceneLayer;
struct UnitSettings;
struct Main;
@@ -61,7 +63,7 @@ struct Main;
_base; \
_base = _setlooper_base_step(&_sce_iter, _base)
-struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base);
+struct BaseLegacy *_setlooper_base_step(struct Scene **sce_iter, struct BaseLegacy *base);
void free_avicodecdata(struct AviCodecData *acd);
void free_qtcodecdata(struct QuicktimeCodecData *acd);
@@ -70,13 +72,15 @@ void BKE_scene_free(struct Scene *sce);
void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
+void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob);
+
/* base functions */
-struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
-struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
-struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
-void BKE_scene_base_unlink(struct Scene *sce, struct Base *base);
+struct BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
+struct BaseLegacy *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
+struct BaseLegacy *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
+void BKE_scene_base_unlink(struct Scene *sce, struct BaseLegacy *base);
void BKE_scene_base_deselect_all(struct Scene *sce);
-void BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
+void BKE_scene_base_select(struct Scene *sce, struct BaseLegacy *selbase);
/* Scene base iteration function.
* Define struct here, so no need to bother with alloc/free it.
@@ -90,10 +94,14 @@ typedef struct SceneBaseIter {
} SceneBaseIter;
int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter,
- struct Scene **scene, int val, struct Base **base, struct Object **ob);
+ struct Scene **scene, int val, struct BaseLegacy **base, struct Object **ob);
-void BKE_scene_base_flag_to_objects(struct Scene *scene);
+void BKE_scene_base_flag_to_objects(struct SceneLayer *sl);
void BKE_scene_base_flag_from_objects(struct Scene *scene);
+void BKE_scene_base_flag_sync_from_base(struct BaseLegacy *base);
+void BKE_scene_base_flag_sync_from_object(struct BaseLegacy *base);
+void BKE_scene_object_base_flag_sync_from_base(struct Base *base);
+void BKE_scene_object_base_flag_sync_from_object(struct Base *base);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 1c5ea946f59..9a60eb29957 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -42,6 +42,7 @@ struct Brush;
struct ColorBand;
struct EnvMap;
struct FreestyleLineStyle;
+struct ImagePool;
struct Lamp;
struct Main;
struct Material;
@@ -133,6 +134,12 @@ struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot);
bool BKE_texture_dependsOnTime(const struct Tex *texture);
bool BKE_texture_is_image_user(const struct Tex *tex);
+void BKE_texture_get_value_ex(
+ const struct Scene *scene, struct Tex *texture,
+ float *tex_co, struct TexResult *texres,
+ struct ImagePool *pool,
+ bool use_color_management);
+
void BKE_texture_get_value(
const struct Scene *scene, struct Tex *texture,
float *tex_co, struct TexResult *texres, bool use_color_management);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index f3bab55b47d..6202c84f320 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -85,6 +85,7 @@ set(SRC
intern/camera.c
intern/cdderivedmesh.c
intern/cloth.c
+ intern/collection.c
intern/collision.c
intern/colortools.c
intern/constraint.c
@@ -157,6 +158,7 @@ set(SRC
intern/pbvh_bmesh.c
intern/pointcache.c
intern/property.c
+ intern/layer.c
intern/report.c
intern/rigidbody.c
intern/sca.c
@@ -214,6 +216,7 @@ set(SRC
BKE_ccg.h
BKE_cdderivedmesh.h
BKE_cloth.h
+ BKE_collection.h
BKE_collision.h
BKE_colortools.h
BKE_constraint.h
@@ -274,6 +277,7 @@ set(SRC
BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
+ BKE_layer.h
BKE_report.h
BKE_rigidbody.h
BKE_sca.h
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index e0bbe345fc4..39f1db0b886 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2216,6 +2216,12 @@ static void mesh_calc_modifiers(
}
}
+ /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (!do_loop_normals && CustomData_has_layer(&finaldm->loopData, CD_NORMAL)) {
+ CustomData_free_layers(&finaldm->loopData, CD_NORMAL, finaldm->numLoopData);
+ }
+
#ifdef WITH_GAMEENGINE
/* NavMesh - this is a hack but saves having a NavMesh modifier */
if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) {
@@ -2551,6 +2557,15 @@ static void editbmesh_calc_modifiers(
/* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
if (!do_loop_normals) {
dm_ensure_display_normals(*r_final);
+
+ /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (CustomData_has_layer(&(*r_final)->loopData, CD_NORMAL)) {
+ CustomData_free_layers(&(*r_final)->loopData, CD_NORMAL, (*r_final)->numLoopData);
+ }
+ if (r_cage && CustomData_has_layer(&(*r_cage)->loopData, CD_NORMAL)) {
+ CustomData_free_layers(&(*r_cage)->loopData, CD_NORMAL, (*r_cage)->numLoopData);
+ }
}
/* add an orco layer if needed */
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 2f65e71c6d2..237e4e80172 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -283,7 +283,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */
static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
{
- Base *base, *baseNext;
+ BaseLegacy *base, *baseNext;
MPathTarget *mpt;
/* make sure our temp-tag isn't already in use */
@@ -321,7 +321,7 @@ static void motionpaths_calc_update_scene(Scene *scene)
BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay);
}
else { /* otherwise we can optimize by restricting updates */
- Base *base, *last = NULL;
+ BaseLegacy *base, *last = NULL;
/* only stuff that moves or needs display still */
DAG_scene_update_flags(G.main, scene, scene->lay, true, false);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 89e93a6384d..2565eb1900c 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1037,6 +1037,17 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
if (use_dverts) {
defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone");
defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * defbase_tot, "defnrToIndex");
+ /* TODO(sergey): Some considerations here:
+ *
+ * - Make it more generic function, maybe even keep together with chanhash.
+ * - Check whether keeping this consistent across frames gives speedup.
+ * - Don't use hash for small armatures.
+ */
+ GHash *idx_hash = BLI_ghash_ptr_new("pose channel index by name");
+ int pchan_index = 0;
+ for (pchan = armOb->pose->chanbase.first; pchan != NULL; pchan = pchan->next, ++pchan_index) {
+ BLI_ghash_insert(idx_hash, pchan, SET_INT_IN_POINTER(pchan_index));
+ }
for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) {
defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name);
/* exclude non-deforming bones */
@@ -1045,10 +1056,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
defnrToPC[i] = NULL;
}
else {
- defnrToPCIndex[i] = BLI_findindex(&armOb->pose->chanbase, defnrToPC[i]);
+ defnrToPCIndex[i] = GET_INT_FROM_POINTER(BLI_ghash_lookup(idx_hash, defnrToPC[i]));
}
}
}
+ BLI_ghash_free(idx_hash, NULL, NULL);
}
}
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index a8670395fc4..afd60102453 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -234,7 +234,7 @@ int BKE_blender_test_break(void)
* \note Don't use MEM_mallocN so functions can be registered at any time.
* \{ */
-struct AtExitData {
+static struct AtExitData {
struct AtExitData *next;
void (*func)(void *user_data);
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 0d509ecea06..57b707a31d3 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -239,7 +239,7 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local)
if (lib_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &brush->id);
- BKE_id_expand_local(&brush->id);
+ BKE_id_expand_local(bmain, &brush->id);
/* enable fake user by default */
id_fake_user_set(&brush->id);
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 264d87b86f3..d0e0c82e3be 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -376,6 +376,45 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r
}
}
+#define V3_MUL_ELEM(a, b) \
+ (a)[0] * (b)[0], \
+ (a)[1] * (b)[1], \
+ (a)[2] * (b)[2]
+
+/* Callback to bvh tree nearest edge to ray.
+ * The tree must have been built using bvhtree_from_mesh_edges.
+ * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
+static void mesh_edges_nearest_to_ray(
+ void *userdata, const float ray_co[3], const float ray_dir[3],
+ const float scale[3], int index, BVHTreeNearest *nearest)
+{
+ struct BVHTreeFromMesh *data = userdata;
+ const MVert *vert = data->vert;
+ const MEdge *e = &data->edge[index];
+
+ const float t0[3] = {V3_MUL_ELEM(vert[e->v1].co, scale)};
+ const float t1[3] = {V3_MUL_ELEM(vert[e->v2].co, scale)};
+ const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
+ const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
+
+ float depth, point[3];
+ const float dist_sq = dist_squared_ray_to_seg_v3(origin_sc, dir_sc, t0, t1, point, &depth);
+
+ if (dist_sq < nearest->dist_sq) {
+ nearest->dist_sq = dist_sq;
+ nearest->index = index;
+
+ point[0] /= scale[0];
+ point[1] /= scale[1];
+ point[2] /= scale[2];
+
+ copy_v3_v3(nearest->co, point);
+ sub_v3_v3v3(nearest->no, t0, t1);
+ }
+}
+
+#undef V3_MUL_ELEM
+
/** \} */
/*
@@ -393,8 +432,6 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
BMEditMesh *em, const int verts_num,
const BLI_bitmap *verts_mask, int verts_num_active)
{
- BVHTree *tree = NULL;
- int i;
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
if (verts_mask) {
BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
@@ -403,15 +440,14 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
verts_num_active = verts_num;
}
- tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
+ BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
if (tree) {
- BMIter iter;
- BMVert *eve;
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ for (int i = 0; i < verts_num; i++) {
if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
continue;
}
+ BMVert *eve = BM_vert_at_index(em->bm, i);
BLI_bvhtree_insert(tree, i, eve->co, 1);
}
BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
@@ -426,28 +462,25 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(
MVert *vert, const int verts_num,
const BLI_bitmap *verts_mask, int verts_num_active)
{
- BVHTree *tree = NULL;
- int i;
- if (vert) {
- if (verts_mask) {
- BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
- }
- else {
- verts_num_active = verts_num;
- }
+ BLI_assert(vert != NULL);
+ if (verts_mask) {
+ BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
+ }
+ else {
+ verts_num_active = verts_num;
+ }
- tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
+ BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
- if (tree) {
- for (i = 0; i < verts_num; i++) {
- if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
- continue;
- }
- BLI_bvhtree_insert(tree, i, vert[i].co, 1);
+ if (tree) {
+ for (int i = 0; i < verts_num; i++) {
+ if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
+ continue;
}
- BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
- BLI_bvhtree_balance(tree);
+ BLI_bvhtree_insert(tree, i, vert[i].co, 1);
}
+ BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
+ BLI_bvhtree_balance(tree);
}
return tree;
@@ -488,11 +521,9 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
const BLI_bitmap *verts_mask, int verts_num_active,
float epsilon, int tree_type, int axis)
{
- int vert_num = em->bm->totvert;
-
BVHTree *tree = bvhtree_from_editmesh_verts_create_tree(
epsilon, tree_type, axis,
- em, vert_num, verts_mask, verts_num_active);
+ em, em->bm->totvert, verts_mask, verts_num_active);
if (tree) {
memset(data, 0, sizeof(*data));
@@ -505,6 +536,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
return tree;
}
+
BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, BMEditMesh *em,
float epsilon, int tree_type, int axis)
@@ -515,8 +547,8 @@ BVHTree *bvhtree_from_editmesh_verts(
epsilon, tree_type, axis);
}
-
-/* Builds a bvh tree where nodes are the vertices of the given dm */
+/* Builds a bvh tree where nodes are the vertices of the given dm
+ * and stores the BVHTree in dm->bvhCache */
BVHTree *bvhtree_from_mesh_verts(
BVHTreeFromMesh *data, DerivedMesh *dm,
float epsilon, int tree_type, int axis)
@@ -557,7 +589,8 @@ BVHTree *bvhtree_from_mesh_verts(
}
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated);
+ bvhtree_from_mesh_verts_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated);
return data->tree;
}
@@ -577,7 +610,8 @@ BVHTree *bvhtree_from_mesh_verts_ex(
epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_verts_setup_data(data, tree, false, epsilon, vert, vert_allocated);
+ bvhtree_from_mesh_verts_setup_data(
+ data, tree, false, epsilon, vert, vert_allocated);
return data->tree;
}
@@ -595,8 +629,6 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
BMEditMesh *em, const int edges_num,
const BLI_bitmap *edges_mask, int edges_num_active)
{
- BVHTree *tree = NULL;
- int i;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE);
if (edges_mask) {
BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num));
@@ -605,9 +637,10 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
edges_num_active = edges_num;
}
- tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
+ BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
if (tree) {
+ int i;
BMIter iter;
BMEdge *eed;
BM_ITER_MESH_INDEX (eed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
@@ -627,6 +660,70 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
return tree;
}
+static BVHTree *bvhtree_from_mesh_edges_create_tree(
+ MVert *vert, MEdge *edge, const int edge_num,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ if (edges_mask) {
+ BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num));
+ }
+ else {
+ edges_num_active = edge_num;
+ }
+ BLI_assert(vert != NULL);
+ BLI_assert(edge != NULL);
+
+ /* Create a bvh-tree of the given target */
+ BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
+ if (tree) {
+ for (int i = 0; i < edge_num; i++) {
+ if (edges_mask && !BLI_BITMAP_TEST_BOOL(edges_mask, i)) {
+ continue;
+ }
+ float co[2][3];
+ copy_v3_v3(co[0], vert[edge[i].v1].co);
+ copy_v3_v3(co[1], vert[edge[i].v2].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 2);
+ }
+ BLI_bvhtree_balance(tree);
+ }
+
+ return tree;
+}
+
+static void bvhtree_from_mesh_edges_setup_data(
+ BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
+ MVert *vert, const bool vert_allocated, MEdge *edge, const bool edge_allocated)
+{
+ memset(data, 0, sizeof(*data));
+ data->tree = tree;
+
+ if (data->tree) {
+ data->cached = is_cached;
+
+ data->nearest_callback = mesh_edges_nearest_point;
+ data->raycast_callback = mesh_edges_spherecast;
+ data->nearest_to_ray_callback = mesh_edges_nearest_to_ray;
+
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->edge = edge;
+ data->edge_allocated = edge_allocated;
+
+ data->sphere_radius = epsilon;
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ if (edge_allocated) {
+ MEM_freeN(edge);
+ }
+ }
+}
+
/* Builds a bvh tree where nodes are the edges of the given em */
BVHTree *bvhtree_from_editmesh_edges_ex(
BVHTreeFromEditMesh *data, BMEditMesh *em,
@@ -651,6 +748,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(
return tree;
}
+
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, BMEditMesh *em,
float epsilon, int tree_type, int axis)
@@ -683,27 +781,13 @@ BVHTree *bvhtree_from_mesh_edges(
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
tree = bvhcache_find(dm->bvhCache, BVHTREE_FROM_EDGES);
if (tree == NULL) {
- int i;
- int numEdges = dm->getNumEdges(dm);
-
- if (vert != NULL && edge != NULL) {
- /* Create a bvh-tree of the given target */
- tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
- if (tree != NULL) {
- for (i = 0; i < numEdges; i++) {
- float co[2][3];
- copy_v3_v3(co[0], vert[edge[i].v1].co);
- copy_v3_v3(co[1], vert[edge[i].v2].co);
-
- BLI_bvhtree_insert(tree, i, co[0], 2);
- }
- BLI_bvhtree_balance(tree);
+ tree = bvhtree_from_mesh_edges_create_tree(
+ vert, edge, dm->getNumEdges(dm),
+ NULL, -1, epsilon, tree_type, axis);
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
- }
- }
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
@@ -711,33 +795,34 @@ BVHTree *bvhtree_from_mesh_edges(
/* printf("BVHTree is already build, using cached tree\n"); */
}
-
/* Setup BVHTreeFromMesh */
- memset(data, 0, sizeof(*data));
- data->tree = tree;
+ bvhtree_from_mesh_edges_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated);
- if (data->tree) {
- data->cached = true;
+ return data->tree;
+}
- data->nearest_callback = mesh_edges_nearest_point;
- data->raycast_callback = mesh_edges_spherecast;
- data->nearest_to_ray_callback = NULL;
+/**
+ * Builds a bvh tree where nodes are the given edges .
+ * \param vert/edge_allocated if true, elem freeing will be done when freeing data.
+ * \param edges_mask if not null, true elements give which vert to add to BVH tree.
+ * \param edges_num_active if >= 0, number of active edges to add to BVH tree (else will be computed from mask).
+ */
+BVHTree *bvhtree_from_mesh_edges_ex(
+ BVHTreeFromMesh *data,
+ MVert *vert, const bool vert_allocated,
+ MEdge *edge, const int edges_num, const bool edge_allocated,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree = bvhtree_from_mesh_edges_create_tree(
+ vert, edge, edges_num, edges_mask, edges_num_active,
+ epsilon, tree_type, axis);
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->edge = edge;
- data->edge_allocated = edge_allocated;
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_edges_setup_data(
+ data, tree, false, epsilon, vert, vert_allocated, edge, edge_allocated);
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- if (edge_allocated) {
- MEM_freeN(edge);
- }
- }
return data->tree;
}
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index deeb35bd880..8630e8562b0 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -205,7 +205,7 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f
/* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */
void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
{
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
@@ -215,7 +215,9 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
if (cache_file == mcmd->cache_file) {
#ifdef WITH_ALEMBIC
- CacheReader_free(mcmd->reader);
+ if (mcmd->reader != NULL) {
+ CacheReader_free(mcmd->reader);
+ }
#endif
mcmd->reader = NULL;
mcmd->object_path[0] = '\0';
@@ -231,7 +233,9 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
if (cache_file == data->cache_file) {
#ifdef WITH_ALEMBIC
- CacheReader_free(data->reader);
+ if (data->reader != NULL) {
+ CacheReader_free(data->reader);
+ }
#endif
data->reader = NULL;
data->object_path[0] = '\0';
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 9cb553aa27b..978204f1cf5 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -853,7 +853,7 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha
}
if (name[0] != '\0') {
- Base *base = BKE_scene_base_find_by_name(scene, name);
+ BaseLegacy *base = BKE_scene_base_find_by_name(scene, name);
if (base) {
return base->object;
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index f2dd2a3fcf6..483fa977aff 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -2398,21 +2398,28 @@ DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps, const bo
use_tessface, em->tottri, (const BMLoop *(*)[3])em->looptris);
}
-static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
+static DerivedMesh *cddm_copy_ex(DerivedMesh *source,
+ const bool need_tessface_data,
+ const bool faces_from_tessfaces)
{
+ const bool copy_tessface_data = (faces_from_tessfaces || need_tessface_data);
CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
DerivedMesh *dm = &cddm->dm;
int numVerts = source->numVertData;
int numEdges = source->numEdgeData;
- int numTessFaces = source->numTessFaceData;
+ int numTessFaces = copy_tessface_data ? source->numTessFaceData : 0;
int numLoops = source->numLoopData;
int numPolys = source->numPolyData;
+ /* NOTE: Don't copy tessellation faces if not requested explicitly. */
+
/* ensure these are created if they are made on demand */
source->getVertDataArray(source, CD_ORIGINDEX);
source->getEdgeDataArray(source, CD_ORIGINDEX);
- source->getTessFaceDataArray(source, CD_ORIGINDEX);
source->getPolyDataArray(source, CD_ORIGINDEX);
+ if (copy_tessface_data) {
+ source->getTessFaceDataArray(source, CD_ORIGINDEX);
+ }
/* this initializes dm, and copies all non mvert/medge/mface layers */
DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces,
@@ -2421,23 +2428,33 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
dm->cd_flag = source->cd_flag;
dm->dirty = source->dirty;
+ /* Tessellation data is never copied, so tag it here. */
+ dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
- CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces);
+ if (copy_tessface_data) {
+ CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces);
+ }
/* now add mvert/medge/mface layers */
cddm->mvert = source->dupVertArray(source);
cddm->medge = source->dupEdgeArray(source);
- cddm->mface = source->dupTessFaceArray(source);
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
- CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces);
-
- if (!faces_from_tessfaces)
+
+ if (faces_from_tessfaces || copy_tessface_data) {
+ cddm->mface = source->dupTessFaceArray(source);
+ CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces);
+ }
+
+ if (!faces_from_tessfaces) {
DM_DupPolys(source, dm);
- else
+ }
+ else {
CDDM_tessfaces_to_faces(dm);
+ }
cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
@@ -2447,12 +2464,17 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
DerivedMesh *CDDM_copy(DerivedMesh *source)
{
- return cddm_copy_ex(source, 0);
+ return cddm_copy_ex(source, false, false);
}
DerivedMesh *CDDM_copy_from_tessface(DerivedMesh *source)
{
- return cddm_copy_ex(source, 1);
+ return cddm_copy_ex(source, false, true);
+}
+
+DerivedMesh *CDDM_copy_with_tessface(DerivedMesh *source)
+{
+ return cddm_copy_ex(source, true, false);
}
/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
new file mode 100644
index 00000000000..289586153ea
--- /dev/null
+++ b/source/blender/blenkernel/intern/collection.c
@@ -0,0 +1,453 @@
+/*
+ * ***** 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): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/collection.c
+ * \ingroup bke
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_iterator.h"
+#include "BLI_listbase.h"
+#include "BLT_translation.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+/**
+ * Add a collection to a collection ListBase and syncronize all render layers
+ * The ListBase is NULL when the collection is to be added to the master collection
+ */
+SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, const char *name)
+{
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
+
+ if (!name) {
+ name = DATA_("New Collection");
+ }
+
+ if (!sc_parent) {
+ sc_parent = sc_master;
+ }
+
+ BLI_strncpy(sc->name, name, sizeof(sc->name));
+ BLI_uniquename(&sc_master->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+
+ BLI_addtail(&sc_parent->scene_collections, sc);
+
+ BKE_layer_sync_new_scene_collection(scene, sc_parent, sc);
+ return sc;
+}
+
+/**
+ * Free the collection items recursively
+ */
+static void collection_free(SceneCollection *sc)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ id_us_min(link->data);
+ }
+ BLI_freelistN(&sc->objects);
+
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ id_us_min(link->data);
+ }
+ BLI_freelistN(&sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ collection_free(nsc);
+ }
+ BLI_freelistN(&sc->scene_collections);
+}
+
+/**
+ * Unlink the collection recursively
+ * return true if unlinked
+ */
+static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone)
+{
+ for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next)
+ {
+ if (sc == sc_gone) {
+ BLI_remlink(&sc_parent->scene_collections, sc_gone);
+ return true;
+ }
+
+ if (collection_remlink(sc, sc_gone)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Recursively remove any instance of this SceneCollection
+ */
+static void layer_collection_remove(SceneLayer *sl, ListBase *lb, const SceneCollection *sc)
+{
+ LayerCollection *lc = lb->first;
+ while(lc) {
+ if (lc->scene_collection == sc) {
+ BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
+ BKE_layer_collection_free(sl, lc);
+ BLI_remlink(lb, lc);
+
+ LayerCollection *lc_next = lc->next;
+ MEM_freeN(lc);
+ lc = lc_next;
+
+ /* only the "top-level" layer collections may have the
+ * same SceneCollection in a sibling tree.
+ */
+ if (lb != &sl->layer_collections) {
+ return;
+ }
+ }
+
+ else {
+ layer_collection_remove(sl, &lc->layer_collections, sc);
+ lc = lc->next;
+ }
+ }
+}
+
+/**
+ * Remove a collection from the scene, and syncronize all render layers
+ */
+bool BKE_collection_remove(Scene *scene, SceneCollection *sc)
+{
+ SceneCollection *sc_master = BKE_collection_master(scene);
+
+ /* the master collection cannot be removed */
+ if (sc == sc_master) {
+ return false;
+ }
+
+ /* unlink from the respective collection tree */
+ if (!collection_remlink(sc_master, sc)) {
+ BLI_assert(false);
+ }
+
+ /* clear the collection items */
+ collection_free(sc);
+
+ /* check all layers that use this collection and clear them */
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ layer_collection_remove(sl, &sl->layer_collections, sc);
+ BKE_scene_layer_base_flag_recalculate(sl);
+ sl->active_collection = 0;
+ }
+
+ MEM_freeN(sc);
+ return true;
+}
+
+/**
+ * Returns the master collection
+ */
+SceneCollection *BKE_collection_master(Scene *scene)
+{
+ return scene->collection;
+}
+
+/**
+ * Free (or release) any data used by the master collection (does not free the master collection itself).
+ * Used only to clear the entire scene data since it's not doing re-syncing of the LayerCollection tree
+ */
+void BKE_collection_master_free(Scene *scene){
+ collection_free(BKE_collection_master(scene));
+}
+
+static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+ id_us_plus((ID *)ob);
+ BKE_layer_sync_object_link(scene, sc, ob);
+}
+
+/**
+ * Add object to collection
+ */
+void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ /* don't add the same object twice */
+ return;
+ }
+ collection_object_add(scene, sc, ob);
+}
+
+/**
+ * Add object to all collections that reference objects is in
+ * (used to copy objects)
+ */
+void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
+{
+ SceneCollection *sc;
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
+ collection_object_add(scene, sc, ob_dst);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+}
+
+/**
+ * Remove object from collection
+ */
+void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us)
+{
+
+ LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
+
+ if (link == NULL) {
+ return;
+ }
+
+ BLI_remlink(&sc->objects, link);
+ MEM_freeN(link);
+
+ TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */
+ BKE_layer_sync_object_unlink(scene, sc, ob);
+
+ if (free_us) {
+ BKE_libblock_free_us(bmain, ob);
+ }
+ else {
+ id_us_min(&ob->id);
+ }
+}
+
+/**
+ * Remove object from all collections of scene
+ */
+void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
+{
+ BKE_scene_remove_rigidbody_object(scene, ob);
+
+ SceneCollection *sc;
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ BKE_collection_object_remove(bmain, scene, sc, ob, free_us);
+ }
+ FOREACH_SCENE_COLLECTION_END
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iteractors */
+/* scene collection iteractor */
+
+typedef struct SceneCollectionsIteratorData {
+ Scene *scene;
+ void **array;
+ int tot, cur;
+ } SceneCollectionsIteratorData;
+
+static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
+{
+ callback(sc, data);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ scene_collection_callback(nsc, callback, data);
+ }
+}
+
+static void scene_collections_count(SceneCollection *UNUSED(sc), void *data)
+{
+ int *tot = data;
+ (*tot)++;
+}
+
+static void scene_collections_build_array(SceneCollection *sc, void *data)
+{
+ SceneCollection ***array = data;
+ **array = sc;
+ (*array)++;
+}
+
+static void scene_collections_array(Scene *scene, SceneCollection ***collections_array, int *tot)
+{
+ SceneCollection *sc = BKE_collection_master(scene);
+ SceneCollection **array;
+
+ *collections_array = NULL;
+ *tot = 0;
+
+ if (scene == NULL)
+ return;
+
+ scene_collection_callback(sc, scene_collections_count, tot);
+
+ if (*tot == 0)
+ return;
+
+ *collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray");
+ scene_collection_callback(sc, scene_collections_build_array, &array);
+}
+
+/**
+ * Only use this in non-performance critical situations
+ * (it iterates over all scene collections twice)
+ */
+void BKE_scene_collections_Iterator_begin(Iterator *iter, void *data_in)
+{
+ Scene *scene = data_in;
+ SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __FUNCTION__);
+
+ data->scene = scene;
+ iter->data = data;
+
+ scene_collections_array(scene, (SceneCollection ***)&data->array, &data->tot);
+ BLI_assert(data->tot != 0);
+
+ data->cur = 0;
+ iter->current = data->array[data->cur];
+ iter->valid = true;
+}
+
+void BKE_scene_collections_Iterator_next(struct Iterator *iter)
+{
+ SceneCollectionsIteratorData *data = iter->data;
+
+ if (++data->cur < data->tot) {
+ iter->current = data->array[data->cur];
+ }
+ else {
+ iter->valid = false;
+ }
+}
+
+void BKE_scene_collections_Iterator_end(struct Iterator *iter)
+{
+ SceneCollectionsIteratorData *data = iter->data;
+
+ if (data) {
+ if (data->array) {
+ MEM_freeN(data->array);
+ }
+ MEM_freeN(data);
+ }
+ iter->valid = false;
+}
+
+
+/* scene objects iteractor */
+
+typedef struct SceneObjectsIteratorData {
+ GSet *visited;
+ LinkData *link;
+ Iterator scene_collection_iter;
+} SceneObjectsIteratorData;
+
+void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ Scene *scene = data_in;
+ SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __FUNCTION__);
+ iter->data = data;
+
+ /* lookup list ot make sure each object is object called once */
+ data->visited = BLI_gset_ptr_new(__func__);
+
+ /* we wrap the scenecollection iterator here to go over the scene collections */
+ BKE_scene_collections_Iterator_begin(&data->scene_collection_iter, scene);
+
+ SceneCollection *sc = data->scene_collection_iter.current;
+ iter->current = sc->objects.first;
+ iter->valid = true;
+
+ if (iter->current == NULL) {
+ BKE_scene_objects_Iterator_next(iter);
+ }
+}
+
+/**
+ * Gets the first unique object in the sequence
+ */
+static LinkData *object_base_unique(GSet *gs, LinkData *link)
+{
+ if (link == NULL) {
+ return NULL;
+ }
+
+ Object *ob = link->data;
+ if (!BLI_gset_haskey(gs, ob)) {
+ BLI_gset_add(gs, ob);
+ return link;
+ }
+ else {
+ return object_base_unique(gs, link->next);
+ }
+}
+
+void BKE_scene_objects_Iterator_next(Iterator *iter)
+{
+ SceneObjectsIteratorData *data = iter->data;
+ LinkData *link = data->link ? object_base_unique(data->visited, data->link->next) : NULL;
+
+ if (link) {
+ data->link = link;
+ iter->current = link->data;
+ }
+ else {
+ /* if this is the last object of this ListBase look at the next SceneCollection */
+ SceneCollection *sc;
+ BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
+ do {
+ sc = data->scene_collection_iter.current;
+ /* get the first unique object of this collection */
+ LinkData *new_link = object_base_unique(data->visited, sc->objects.first);
+ if (new_link) {
+ data->link = new_link;
+ iter->current = data->link->data;
+ return;
+ }
+ BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
+ } while (data->scene_collection_iter.valid);
+
+ if (!data->scene_collection_iter.valid) {
+ iter->valid = false;
+ }
+ }
+}
+
+void BKE_scene_objects_Iterator_end(Iterator *iter)
+{
+ SceneObjectsIteratorData *data = iter->data;
+ if (data) {
+ BKE_scene_collections_Iterator_end(&data->scene_collection_iter);
+ BLI_gset_free(data->visited, NULL);
+ MEM_freeN(data);
+ }
+}
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index ee25be36855..b5f76240c0b 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -514,7 +514,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
// collision object will exclude self
Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
{
- Base *base;
+ BaseLegacy *base;
Object **objs;
GroupObject *go;
unsigned int numobj= 0, maxobj= 100;
@@ -596,7 +596,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
}
else {
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4c01bfd35f2..a7c53dda8c7 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -47,6 +47,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_sound.h"
@@ -814,6 +815,14 @@ struct SpaceClip *CTX_wm_space_clip(const bContext *C)
return NULL;
}
+struct SpaceCollections *CTX_wm_space_collections(const bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype == SPACE_COLLECTIONS)
+ return sa->spacedata.first;
+ return NULL;
+}
+
void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
{
C->wm.manager = wm;
@@ -836,8 +845,9 @@ void CTX_wm_window_set(bContext *C, wmWindow *win)
void CTX_wm_screen_set(bContext *C, bScreen *screen)
{
C->wm.screen = screen;
- if (C->wm.screen)
- C->data.scene = C->wm.screen->scene;
+ if (C->wm.screen) {
+ CTX_data_scene_set(C, C->wm.screen->scene);
+ }
C->wm.area = NULL;
C->wm.region = NULL;
}
@@ -896,6 +906,59 @@ Scene *CTX_data_scene(const bContext *C)
return C->data.scene;
}
+SceneLayer *CTX_data_scene_layer(const bContext *C)
+{
+ SceneLayer *sl;
+
+ if (ctx_data_pointer_verify(C, "render_layer", (void *)&sl)) {
+ return sl;
+ }
+ else {
+ return BKE_scene_layer_active(CTX_data_scene(C));
+ }
+}
+
+/**
+ * This is tricky. Sometimes the user overrides the render_layer
+ * but not the scene_collection. In this case what to do?
+ *
+ * If the scene_collection is linked to the SceneLayer we use it.
+ * Otherwise we fallback to the active one of the SceneLayer.
+ */
+LayerCollection *CTX_data_layer_collection(const bContext *C)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ LayerCollection *lc;
+
+ if (ctx_data_pointer_verify(C, "layer_collection", (void *)&lc)) {
+ if (BKE_scene_layer_has_collection(sl, lc->scene_collection)) {
+ return lc;
+ }
+ }
+
+ /* fallback */
+ return BKE_layer_collection_active(sl);
+}
+
+SceneCollection *CTX_data_scene_collection(const bContext *C)
+{
+ SceneCollection *sc;
+ if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) {
+ if (BKE_scene_layer_has_collection(CTX_data_scene_layer(C), sc)) {
+ return sc;
+ }
+ }
+
+ LayerCollection *lc = CTX_data_layer_collection(C);
+ if (lc) {
+ return lc->scene_collection;
+ }
+
+ /* fallback */
+ Scene *scene = CTX_data_scene(C);
+ return BKE_collection_master(scene);
+}
+
int CTX_data_mode_enum(const bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 98d37fb07bf..c9f0b8ec9ca 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2595,7 +2595,7 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, Custom
if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT))
return false;
-#undef TEST_RET
+#undef LAYER_CMP
/* if no layers are on either CustomData's,
* then there was nothing to do... */
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index bc9871aee54..39d06a13e6e 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -488,7 +488,7 @@ static void scene_setSubframe(Scene *scene, float subframe)
static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene)
{
- Base *base = NULL;
+ BaseLegacy *base = NULL;
GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
@@ -5780,7 +5780,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
* Loop through surface's target paint objects and do painting
*/
{
- Base *base = NULL;
+ BaseLegacy *base = NULL;
GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index fe8f5ebdca6..668d4d6c9e2 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -209,7 +209,7 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
EffectorWeights *weights, bool for_simulation)
{
- Base *base;
+ BaseLegacy *base;
unsigned int layer= ob_src->lay;
ListBase *effectors = NULL;
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 9b011dbb003..9c81a8b49be 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -130,18 +130,11 @@ static bool group_object_add_internal(Group *group, Object *ob)
return true;
}
-bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_add(Group *group, Object *object)
{
if (group_object_add_internal(group, object)) {
if ((object->flag & OB_FROMGROUP) == 0) {
-
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag |= OB_FROMGROUP;
-
- if (base)
- base->flag |= OB_FROMGROUP;
}
return true;
}
@@ -208,18 +201,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
return group_object_cyclic_check_internal(object, group);
}
-bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_unlink(Group *group, Object *object)
{
if (group_object_unlink_internal(group, object)) {
/* object can be NULL */
if (object && BKE_group_object_find(NULL, object) == NULL) {
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag &= ~OB_FROMGROUP;
-
- if (base)
- base->flag &= ~OB_FROMGROUP;
}
return true;
}
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index d098366aef4..69a2067f4e6 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -174,15 +174,10 @@ void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool lib_local)
void BKE_lamp_free(Lamp *la)
{
- MTex *mtex;
int a;
for (a = 0; a < MAX_MTEX; a++) {
- mtex = la->mtex[a];
- if (mtex && mtex->tex)
- id_us_min(&mtex->tex->id);
- if (mtex)
- MEM_freeN(mtex);
+ MEM_SAFE_FREE(la->mtex[a]);
}
BKE_animdata_free((ID *)la, false);
@@ -193,6 +188,7 @@ void BKE_lamp_free(Lamp *la)
if (la->nodetree) {
ntreeFreeTree(la->nodetree);
MEM_freeN(la->nodetree);
+ la->nodetree = NULL;
}
BKE_previewimg_free(&la->preview);
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
new file mode 100644
index 00000000000..ef4816af54d
--- /dev/null
+++ b/source/blender/blenkernel/intern/layer.c
@@ -0,0 +1,1096 @@
+/*
+ * ***** 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): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/layer.c
+ * \ingroup bke
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLT_translation.h"
+
+#include "BKE_layer.h"
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+/* prototype */
+struct CollectionEngineSettingsCB_Type;
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
+static CollectionEngineSettings *collection_engine_settings_create(struct CollectionEngineSettingsCB_Type *ces_type);
+static void layer_collection_engine_settings_free(LayerCollection *lc);
+static void layer_collection_create_engine_settings(LayerCollection *lc);
+static void scene_layer_engine_settings_update(SceneLayer *sl, Object *ob, const char *engine_name);
+static void object_bases_Iterator_next(Iterator *iter, const int flag);
+
+/* RenderLayer */
+
+/**
+ * Returns the SceneLayer to be used for rendering
+ */
+SceneLayer *BKE_scene_layer_active(struct Scene *scene)
+{
+ SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer);
+ BLI_assert(sl);
+ return sl;
+}
+
+/**
+ * Add a new renderlayer
+ * by default, a renderlayer has the master collection
+ */
+SceneLayer *BKE_scene_layer_add(Scene *scene, const char *name)
+{
+ if (!name) {
+ name = DATA_("Render Layer");
+ }
+
+ SceneLayer *sl = MEM_callocN(sizeof(SceneLayer), "Scene Layer");
+ sl->flag |= SCENE_LAYER_RENDER;
+
+ BLI_addtail(&scene->render_layers, sl);
+
+ /* unique name */
+ BLI_strncpy_utf8(sl->name, name, sizeof(sl->name));
+ BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name));
+
+ SceneCollection *sc = BKE_collection_master(scene);
+ layer_collection_add(sl, &sl->layer_collections, sc);
+
+ return sl;
+}
+
+bool BKE_scene_layer_remove(Main *bmain, Scene *scene, SceneLayer *sl)
+{
+ const int act = BLI_findindex(&scene->render_layers, sl);
+
+ if (act == -1) {
+ return false;
+ }
+ else if ( (scene->render_layers.first == scene->render_layers.last) &&
+ (scene->render_layers.first == sl))
+ {
+ /* ensure 1 layer is kept */
+ return false;
+ }
+
+ BLI_remlink(&scene->render_layers, sl);
+
+ BKE_scene_layer_free(sl);
+ MEM_freeN(sl);
+
+ scene->active_layer = 0;
+ /* TODO WORKSPACE: set active_layer to 0 */
+
+ for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree) {
+ BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Free (or release) any data used by this SceneLayer (does not free the SceneLayer itself).
+ */
+void BKE_scene_layer_free(SceneLayer *sl)
+{
+ sl->basact = NULL;
+ BLI_freelistN(&sl->object_bases);
+
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_free(NULL, lc);
+ }
+ BLI_freelistN(&sl->layer_collections);
+}
+
+/**
+ * Set the render engine of a renderlayer
+ */
+void BKE_scene_layer_engine_set(SceneLayer *sl, const char *engine)
+{
+ BLI_strncpy_utf8(sl->engine, engine, sizeof(sl->engine));
+}
+
+/**
+ * Tag all the selected objects of a renderlayer
+ */
+void BKE_scene_layer_selected_objects_tag(SceneLayer *sl, const int tag)
+{
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ base->object->flag |= tag;
+ }
+ else {
+ base->object->flag &= ~tag;
+ }
+ }
+}
+
+static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc)
+{
+ for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) {
+ if (lcn == lc) {
+ return true;
+ }
+ if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Find the SceneLayer a LayerCollection belongs to
+ */
+SceneLayer *BKE_scene_layer_find_from_collection(Scene *scene, LayerCollection *lc)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ if (find_scene_collection_in_scene_collections(&sl->layer_collections, lc)) {
+ return sl;
+ }
+ }
+ return NULL;
+}
+
+/* Base */
+
+Base *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob)
+{
+ return BLI_findptr(&sl->object_bases, ob, offsetof(Base, object));
+}
+
+void BKE_scene_layer_base_deselect_all(SceneLayer *sl)
+{
+ Base *base;
+
+ for (base = sl->object_bases.first; base; base = base->next) {
+ base->flag &= ~BASE_SELECTED;
+ }
+}
+
+void BKE_scene_layer_base_select(struct SceneLayer *sl, Base *selbase)
+{
+ sl->basact = selbase;
+ if ((selbase->flag & BASE_SELECTABLED) != 0) {
+ selbase->flag |= BASE_SELECTED;
+ }
+}
+
+static void scene_layer_object_base_unref(SceneLayer* sl, Base *base)
+{
+ base->refcount--;
+
+ /* It only exists in the RenderLayer */
+ if (base->refcount == 0) {
+ if (sl->basact == base) {
+ sl->basact = NULL;
+ }
+
+ BLI_remlink(&sl->object_bases, base);
+ MEM_freeN(base);
+ }
+}
+
+static void layer_collection_base_flag_recalculate(LayerCollection *lc, const bool tree_is_visible, const bool tree_is_selectable)
+{
+ bool is_visible = tree_is_visible && ((lc->flag & COLLECTION_VISIBLE) != 0);
+ /* an object can only be selected if it's visible */
+ bool is_selectable = tree_is_selectable && is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
+
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ Base *base = link->data;
+
+ if (is_visible) {
+ base->flag |= BASE_VISIBLED;
+ }
+ else {
+ base->flag &= ~BASE_VISIBLED;
+ }
+
+ if (is_selectable) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ else {
+ base->flag &= ~BASE_SELECTABLED;
+ }
+ }
+
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ layer_collection_base_flag_recalculate(lcn, is_visible, is_selectable);
+ }
+}
+
+/**
+ * Re-evaluate the ObjectBase flags for SceneLayer
+ */
+void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl)
+{
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_base_flag_recalculate(lc, true, true);
+ }
+
+ /* if base is not selectabled, clear select */
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) == 0) {
+ base->flag &= ~BASE_SELECTED;
+ }
+ }
+}
+
+/**
+ * Tag Scene Layer to recalculation
+ *
+ * Temporary function, waiting for real depsgraph
+ */
+void BKE_scene_layer_engine_settings_recalculate(SceneLayer *sl)
+{
+ sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
+ }
+}
+
+/**
+ * Tag Object in SceneLayer to recalculation
+ *
+ * Temporary function, waiting for real depsgraph
+ */
+void BKE_scene_layer_engine_settings_object_recalculate(SceneLayer *sl, Object *ob)
+{
+ Base *base = BLI_findptr(&sl->object_bases, ob, offsetof(Base, object));
+ if (base) {
+ sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
+ base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
+ }
+}
+
+/**
+ * Tag all Objects in LayerCollection to recalculation
+ *
+ * Temporary function, waiting for real depsgraph
+ */
+void BKE_scene_layer_engine_settings_collection_recalculate(SceneLayer *sl, LayerCollection *lc)
+{
+ sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
+
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ Base *base = (Base *)link->data;
+ base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
+ }
+
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ BKE_scene_layer_engine_settings_collection_recalculate(sl, lcn);
+ }
+}
+
+/**
+ * Re-calculate the engine settings for all the objects in SceneLayer
+ *
+ * Temporary function, waiting for real depsgraph
+ */
+void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl, const char *engine_name)
+{
+ if ((sl->flag & SCENE_LAYER_ENGINE_DIRTY) == 0) {
+ return;
+ }
+
+ /* do the complete settings update */
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if (((base->flag & BASE_DIRTY_ENGINE_SETTINGS) != 0) && \
+ (base->flag & BASE_VISIBLED) != 0)
+ {
+ scene_layer_engine_settings_update(sl, base->object, engine_name);
+ base->flag &= ~BASE_DIRTY_ENGINE_SETTINGS;
+ }
+ }
+
+ sl->flag &= ~SCENE_LAYER_ENGINE_DIRTY;
+}
+
+/**
+ * Return the base if existent, or create it if necessary
+ * Always bump the refcount
+ */
+static Base *object_base_add(SceneLayer *sl, Object *ob)
+{
+ Base *base;
+ base = BKE_scene_layer_base_find(sl, ob);
+
+ if (base == NULL) {
+ base = MEM_callocN(sizeof(Base), "Object Base");
+
+ /* do not bump user count, leave it for SceneCollections */
+ base->object = ob;
+ BLI_addtail(&sl->object_bases, base);
+ }
+ base->refcount++;
+ return base;
+}
+
+/* LayerCollection */
+
+/**
+ * When freeing the entire SceneLayer at once we don't bother with unref
+ * otherwise SceneLayer is passed to keep the syncing of the LayerCollection tree
+ */
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
+{
+ if (sl) {
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ scene_layer_object_base_unref(sl, link->data);
+ }
+ }
+
+ BLI_freelistN(&lc->object_bases);
+ BLI_freelistN(&lc->overrides);
+ layer_collection_engine_settings_free(lc);
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ layer_collection_free(sl, nlc);
+ }
+
+ BLI_freelistN(&lc->layer_collections);
+}
+
+/**
+ * Free (or release) LayerCollection from SceneLayer
+ * (does not free the LayerCollection itself).
+ */
+void BKE_layer_collection_free(SceneLayer *sl, LayerCollection *lc)
+{
+ layer_collection_free(sl, lc);
+}
+
+/* LayerCollection */
+
+/**
+ * Recursively get the collection for a given index
+ */
+static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ if (*i == number) {
+ return lc;
+ }
+
+ (*i)++;
+
+ LayerCollection *lc_nested = collection_from_index(&lc->layer_collections, number, i);
+ if (lc_nested) {
+ return lc_nested;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Get the active collection
+ */
+LayerCollection *BKE_layer_collection_active(SceneLayer *sl)
+{
+ int i = 0;
+ return collection_from_index(&sl->layer_collections, sl->active_collection, &i);
+}
+
+/**
+ * Recursively get the count of collections
+ */
+static int collection_count(ListBase *lb)
+{
+ int i = 0;
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ i += collection_count(&lc->layer_collections) + 1;
+ }
+ return i;
+}
+
+/**
+ * Get the total number of collections
+ * (including all the nested collections)
+ */
+int BKE_layer_collection_count(SceneLayer *sl)
+{
+ return collection_count(&sl->layer_collections);
+}
+
+/**
+ * Recursively get the index for a given collection
+ */
+static int index_from_collection(ListBase *lb, LayerCollection *lc, int *i)
+{
+ for (LayerCollection *lcol = lb->first; lcol; lcol = lcol->next) {
+ if (lcol == lc) {
+ return *i;
+ }
+
+ (*i)++;
+
+ int i_nested = index_from_collection(&lcol->layer_collections, lc, i);
+ if (i_nested != -1) {
+ return i_nested;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Return -1 if not found
+ */
+int BKE_layer_collection_findindex(SceneLayer *sl, LayerCollection *lc)
+{
+ int i = 0;
+ return index_from_collection(&sl->layer_collections, lc, &i);
+}
+
+/**
+ * Link a collection to a renderlayer
+ * The collection needs to be created separately
+ */
+LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc)
+{
+ LayerCollection *lc = layer_collection_add(sl, &sl->layer_collections, sc);
+ sl->active_collection = BKE_layer_collection_findindex(sl, lc);
+ return lc;
+}
+
+/**
+ * Unlink a collection base from a renderlayer
+ * The corresponding collection is not removed from the master collection
+ */
+void BKE_collection_unlink(SceneLayer *sl, LayerCollection *lc)
+{
+ BKE_layer_collection_free(sl, lc);
+ BKE_scene_layer_base_flag_recalculate(sl);
+ BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
+
+ BLI_remlink(&sl->layer_collections, lc);
+ MEM_freeN(lc);
+ sl->active_collection = 0;
+}
+
+static void layer_collection_object_add(SceneLayer *sl, LayerCollection *lc, Object *ob)
+{
+ Base *base = object_base_add(sl, ob);
+
+ /* only add an object once - prevent SceneCollection->objects and
+ * SceneCollection->filter_objects to add the same object */
+
+ if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) {
+ return;
+ }
+
+ BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
+
+ BKE_scene_layer_base_flag_recalculate(sl);
+ BKE_scene_layer_engine_settings_object_recalculate(sl, ob);
+}
+
+static void layer_collection_object_remove(SceneLayer *sl, LayerCollection *lc, Object *ob)
+{
+ Base *base;
+ base = BKE_scene_layer_base_find(sl, ob);
+
+ LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data));
+ BLI_remlink(&lc->object_bases, link);
+ MEM_freeN(link);
+
+ scene_layer_object_base_unref(sl, base);
+}
+
+static void layer_collection_objects_populate(SceneLayer *sl, LayerCollection *lc, ListBase *objects)
+{
+ for (LinkData *link = objects->first; link; link = link->next) {
+ layer_collection_object_add(sl, lc, link->data);
+ }
+}
+
+static void layer_collection_populate(SceneLayer *sl, LayerCollection *lc, SceneCollection *sc)
+{
+ layer_collection_objects_populate(sl, lc, &sc->objects);
+ layer_collection_objects_populate(sl, lc, &sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ layer_collection_add(sl, &lc->layer_collections, nsc);
+ }
+}
+
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc)
+{
+ LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
+ BLI_addtail(lb, lc);
+
+ lc->scene_collection = sc;
+ lc->flag = COLLECTION_VISIBLE + COLLECTION_SELECTABLE + COLLECTION_FOLDED;
+
+ layer_collection_create_engine_settings(lc);
+ layer_collection_populate(sl, lc, sc);
+ return lc;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+/**
+ * See if render layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc)
+{
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * See if the object is in any of the scene layers of the scene
+ */
+bool BKE_scene_has_object(Scene *scene, Object *ob)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+ if (base) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* Syncing */
+
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
+{
+ if (lc->scene_collection == sc) {
+ return lc;
+ }
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc);
+ if (found) {
+ return found;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Add a new LayerCollection for all the SceneLayers that have sc_parent
+ */
+void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc_parent, SceneCollection *sc)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent);
+ if (lc_parent) {
+ layer_collection_add(sl, &lc_parent->layer_collections, sc);
+ }
+ }
+ }
+}
+
+/**
+ * Add a corresponding ObjectBase to all the equivalent LayerCollection
+ */
+void BKE_layer_sync_object_link(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_add(sl, found, ob);
+ }
+ }
+ }
+}
+
+/**
+ * Remove the equivalent object base to all layers that have this collection
+ * also remove all reference to ob in the filter_objects
+ */
+void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_remove(sl, found, ob);
+ }
+ }
+ BKE_scene_layer_base_flag_recalculate(sl);
+ BKE_scene_layer_engine_settings_object_recalculate(sl, ob);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Override */
+
+/**
+ * Add a new datablock override
+ */
+void BKE_collection_override_datablock_add(LayerCollection *UNUSED(lc), const char *UNUSED(data_path), ID *UNUSED(id))
+{
+ TODO_LAYER_OVERRIDE;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Engine Settings */
+
+ListBase R_engines_settings_callbacks = {NULL, NULL};
+
+typedef struct CollectionEngineSettingsCB_Type {
+ struct CollectionEngineSettingsCB_Type *next, *prev;
+
+ char name[MAX_NAME]; /* engine name */
+
+ CollectionEngineSettingsCB callback;
+
+} CollectionEngineSettingsCB_Type;
+
+static void create_engine_settings_layer_collection(LayerCollection *lc, CollectionEngineSettingsCB_Type *ces_type)
+{
+ if (BKE_layer_collection_engine_get(lc, ces_type->name)) {
+ return;
+ }
+
+ CollectionEngineSettings *ces = collection_engine_settings_create(ces_type);
+ BLI_addtail(&lc->engine_settings, ces);
+
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ create_engine_settings_layer_collection(lcn, ces_type);
+ }
+}
+
+static void create_engines_settings_scene(Scene *scene, CollectionEngineSettingsCB_Type *ces_type)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ create_engine_settings_layer_collection(lc, ces_type);
+ }
+ }
+}
+
+void BKE_layer_collection_engine_settings_callback_register(
+ Main *bmain, const char *engine_name, CollectionEngineSettingsCB func)
+{
+ CollectionEngineSettingsCB_Type *ces_type;
+
+ /* cleanup in case it existed */
+ ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
+
+ if (ces_type) {
+ BLI_remlink(&R_engines_settings_callbacks, ces_type);
+ MEM_freeN(ces_type);
+ }
+
+ ces_type = MEM_callocN(sizeof(CollectionEngineSettingsCB_Type), "collection_engine_type");
+ BLI_strncpy_utf8(ces_type->name, engine_name, sizeof(ces_type->name));
+ ces_type->callback = func;
+ BLI_addtail(&R_engines_settings_callbacks, ces_type);
+
+ if (bmain) {
+ /* populate all of the collections of the scene with those settings */
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ create_engines_settings_scene(scene, ces_type);
+ }
+ }
+}
+
+void BKE_layer_collection_engine_settings_callback_free(void)
+{
+ BLI_freelistN(&R_engines_settings_callbacks);
+}
+
+static CollectionEngineSettings *collection_engine_settings_create(CollectionEngineSettingsCB_Type *ces_type)
+{
+ /* create callback data */
+ CollectionEngineSettings *ces = MEM_callocN(sizeof(CollectionEngineSettings), "Collection Engine Settings");
+ BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name));
+
+ /* call callback */
+ ces_type->callback(NULL, ces);
+
+ return ces;
+}
+
+/**
+ * Initialize a CollectionEngineSettings
+ *
+ * Usually we would pass LayerCollection->engine_settings
+ * But depsgraph uses this for Object->collection_settings
+ */
+CollectionEngineSettings *BKE_layer_collection_engine_settings_create(const char *engine_name)
+{
+ CollectionEngineSettingsCB_Type *ces_type;
+ ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
+ BLI_assert(ces_type);
+
+ CollectionEngineSettings *ces = collection_engine_settings_create(ces_type);
+ return ces;
+}
+
+/**
+ * Free the CollectionEngineSettings
+ */
+void BKE_layer_collection_engine_settings_free(CollectionEngineSettings *ces)
+{
+ BLI_freelistN(&ces->properties);
+}
+
+static void layer_collection_engine_settings_free(LayerCollection *lc)
+{
+ for (CollectionEngineSettings *ces = lc->engine_settings.first; ces; ces = ces->next) {
+ BKE_layer_collection_engine_settings_free(ces);
+ }
+ BLI_freelistN(&lc->engine_settings);
+}
+
+/**
+ * Initialize the render settings for a single LayerCollection
+ */
+static void layer_collection_create_engine_settings(LayerCollection *lc)
+{
+ CollectionEngineSettingsCB_Type *ces_type;
+ for (ces_type = R_engines_settings_callbacks.first; ces_type; ces_type = ces_type->next) {
+ create_engine_settings_layer_collection(lc, ces_type);
+ }
+}
+
+/**
+ * Return layer collection engine settings for specified engine
+ */
+CollectionEngineSettings *BKE_layer_collection_engine_get(LayerCollection *lc, const char *engine_name)
+{
+ CollectionEngineSettings *ces;
+ ces = BLI_findstring(&lc->engine_settings, engine_name, offsetof(CollectionEngineSettings, name));
+ return ces;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Engine Settings Properties */
+
+void BKE_collection_engine_property_add_float(CollectionEngineSettings *ces, const char *name, float value)
+{
+ CollectionEnginePropertyFloat *prop;
+ prop = MEM_callocN(sizeof(CollectionEnginePropertyFloat), "collection engine settings float");
+ prop->data.type = COLLECTION_PROP_TYPE_FLOAT;
+ BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
+ prop->value = value;
+ BLI_addtail(&ces->properties, prop);
+}
+
+void BKE_collection_engine_property_add_int(CollectionEngineSettings *ces, const char *name, int value)
+{
+ CollectionEnginePropertyInt *prop;
+ prop = MEM_callocN(sizeof(CollectionEnginePropertyInt), "collection engine settings int");
+ prop->data.type = COLLECTION_PROP_TYPE_INT;
+ BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
+ prop->value = value;
+ BLI_addtail(&ces->properties, prop);
+}
+
+CollectionEngineProperty *BKE_collection_engine_property_get(CollectionEngineSettings *ces, const char *name)
+{
+ return BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+}
+
+int BKE_collection_engine_property_value_get_int(CollectionEngineSettings *ces, const char *name)
+{
+ CollectionEnginePropertyInt *prop;
+ prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+ return prop->value;
+}
+
+float BKE_collection_engine_property_value_get_float(CollectionEngineSettings *ces, const char *name)
+{
+ CollectionEnginePropertyFloat *prop;
+ prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+ return prop->value;
+}
+
+void BKE_collection_engine_property_value_set_int(CollectionEngineSettings *ces, const char *name, int value)
+{
+ CollectionEnginePropertyInt *prop;
+ prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+ prop->value = value;
+ prop->data.flag |= COLLECTION_PROP_USE;
+}
+
+void BKE_collection_engine_property_value_set_float(CollectionEngineSettings *ces, const char *name, float value)
+{
+ CollectionEnginePropertyFloat *prop;
+ prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+ prop->value = value;
+ prop->data.flag |= COLLECTION_PROP_USE;
+}
+
+bool BKE_collection_engine_property_use_get(CollectionEngineSettings *ces, const char *name)
+{
+ CollectionEngineProperty *prop;
+ prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+ return ((prop->flag & COLLECTION_PROP_USE) != 0);
+}
+
+void BKE_collection_engine_property_use_set(CollectionEngineSettings *ces, const char *name, bool value)
+{
+ CollectionEngineProperty *prop;
+ prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+
+ if (value) {
+ prop->flag |= COLLECTION_PROP_USE;
+ }
+ else {
+ prop->flag &= ~COLLECTION_PROP_USE;
+ }
+}
+
+/* Engine Settings recalculate */
+
+static void collection_engine_settings_init(CollectionEngineSettings *ces, const char *engine_name)
+{
+ CollectionEngineSettingsCB_Type *ces_type;
+ ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
+
+ BLI_listbase_clear(&ces->properties);
+ BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name));
+
+ /* call callback */
+ ces_type->callback(NULL, ces);
+}
+
+static void collection_engine_settings_copy(CollectionEngineSettings *ces_dst, CollectionEngineSettings *ces_src)
+{
+ BLI_strncpy_utf8(ces_dst->name, ces_src->name, sizeof(ces_dst->name));
+ BLI_freelistN(&ces_dst->properties);
+
+ for (CollectionEngineProperty *prop = ces_src->properties.first; prop; prop = prop->next) {
+ CollectionEngineProperty *prop_new = MEM_dupallocN(prop);
+ BLI_addtail(&ces_dst->properties, prop_new);
+ }
+}
+
+/**
+ * Set a value from a CollectionProperty to another
+ */
+static void collection_engine_property_set (CollectionEngineProperty *prop_dst, CollectionEngineProperty *prop_src){
+ if ((prop_src->flag & COLLECTION_PROP_USE) != 0) {
+ /* mark the property as used, so the engine knows if the value was ever set*/
+ prop_dst->flag |= COLLECTION_PROP_USE;
+ switch (prop_src->type) {
+ case COLLECTION_PROP_TYPE_FLOAT:
+ ((CollectionEnginePropertyFloat *)prop_dst)->value = ((CollectionEnginePropertyFloat *)prop_src)->value;
+ break;
+ case COLLECTION_PROP_TYPE_INT:
+ ((CollectionEnginePropertyInt *)prop_dst)->value = ((CollectionEnginePropertyInt *)prop_src)->value;
+ break;
+ default:
+ BLI_assert(false);
+ break;
+ }
+ }
+}
+
+static void collection_engine_settings_merge(CollectionEngineSettings *ces_dst, CollectionEngineSettings *ces_src)
+{
+ CollectionEngineProperty *prop_src, *prop_dst;
+
+ prop_dst = ces_dst->properties.first;
+ for (prop_src = ces_src->properties.first; prop_src; prop_src = prop_src->next, prop_dst = prop_dst->next) {
+ collection_engine_property_set(prop_dst, prop_src);
+ }
+}
+
+static void layer_collection_engine_settings_update(
+ LayerCollection *lc, CollectionEngineSettings *ces_parent,
+ Base *base, CollectionEngineSettings *ces_ob)
+{
+ if ((lc->flag & COLLECTION_VISIBLE) == 0) {
+ return;
+ }
+
+ CollectionEngineSettings ces = {NULL};
+ collection_engine_settings_copy(&ces, ces_parent);
+
+ CollectionEngineSettings *ces_lc = BKE_layer_collection_engine_get(lc, ces.name);
+ collection_engine_settings_merge(&ces, ces_lc);
+
+ if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data)) != NULL) {
+ collection_engine_settings_merge(ces_ob, &ces);
+ }
+
+ /* do it recursively */
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ layer_collection_engine_settings_update(lcn, &ces, base, ces_ob);
+ }
+
+ BKE_layer_collection_engine_settings_free(&ces);
+}
+
+/**
+ * Update the collection settings pointer allocated in the object
+ * This is to be flushed from the Depsgraph
+ */
+static void scene_layer_engine_settings_update(SceneLayer *sl, Object *ob, const char *engine_name)
+{
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+ CollectionEngineSettings ces_layer = {NULL}, *ces_ob;
+
+ collection_engine_settings_init(&ces_layer, engine_name);
+
+ if (ob->collection_settings) {
+ BKE_layer_collection_engine_settings_free(ob->collection_settings);
+ MEM_freeN(ob->collection_settings);
+ }
+
+ CollectionEngineSettingsCB_Type *ces_type;
+ ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
+ ces_ob = collection_engine_settings_create(ces_type);
+
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_engine_settings_update(lc, &ces_layer, base, ces_ob);
+ }
+
+ BKE_layer_collection_engine_settings_free(&ces_layer);
+ ob->collection_settings = ces_ob;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iterators */
+
+static void object_bases_Iterator_begin(Iterator *iter, void *data_in, const int flag)
+{
+ SceneLayer *sl = data_in;
+ Base *base = sl->object_bases.first;
+
+ /* when there are no objects */
+ if (base == NULL) {
+ iter->valid = false;
+ return;
+ }
+
+ iter->valid = true;
+ iter->data = base;
+
+ if ((base->flag & flag) == 0) {
+ object_bases_Iterator_next(iter, flag);
+ }
+ else {
+ iter->current = base;
+ }
+}
+
+static void object_bases_Iterator_next(Iterator *iter, const int flag)
+{
+ Base *base = ((Base *)iter->data)->next;
+
+ while (base) {
+ if ((base->flag & flag) != 0) {
+ iter->current = base;
+ iter->data = base;
+ return;
+ }
+ base = base->next;
+ }
+
+ iter->current = NULL;
+ iter->valid = false;
+}
+
+static void objects_Iterator_begin(Iterator *iter, void *data_in, const int flag)
+{
+ object_bases_Iterator_begin(iter, data_in, flag);
+
+ if (iter->valid) {
+ iter->current = ((Base *)iter->current)->object;
+ }
+}
+
+static void objects_Iterator_next(Iterator *iter, const int flag)
+{
+ object_bases_Iterator_next(iter, flag);
+
+ if (iter->valid) {
+ iter->current = ((Base *)iter->current)->object;
+ }
+}
+
+void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ objects_Iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_objects_Iterator_next(Iterator *iter)
+{
+ objects_Iterator_next(iter, BASE_SELECTED);
+}
+
+void BKE_selected_objects_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ objects_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_next(Iterator *iter)
+{
+ objects_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in)
+{
+ object_bases_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_next(Iterator *iter)
+{
+ object_bases_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index de35d1e0eac..2398c6724ed 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -76,6 +76,7 @@
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
+#include "BLI_mempool.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
@@ -273,8 +274,12 @@ void BKE_id_clear_newpoin(ID *id)
}
static int id_expand_local_callback(
- void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int UNUSED(cd_flag))
+ void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
/* Can hapen that we get unlinkable ID here, e.g. with shapekey referring to itself (through drivers)...
* Just skip it, shape key can only be either indirectly linked, or fully local, period.
* And let's curse one more time that stupid useless shapekey ID type! */
@@ -288,9 +293,9 @@ static int id_expand_local_callback(
/**
* Expand ID usages of given id as 'extern' (and no more indirect) linked data. Used by ID copy/make_local functions.
*/
-void BKE_id_expand_local(ID *id)
+void BKE_id_expand_local(Main *bmain, ID *id)
{
- BKE_library_foreach_ID_link(id, id_expand_local_callback, NULL, 0);
+ BKE_library_foreach_ID_link(bmain, id, id_expand_local_callback, NULL, IDWALK_READONLY);
}
/**
@@ -299,7 +304,7 @@ void BKE_id_expand_local(ID *id)
void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id)
{
if (ID_IS_LINKED_DATABLOCK(old_id)) {
- BKE_id_expand_local(new_id);
+ BKE_id_expand_local(bmain, new_id);
BKE_id_lib_local_paths(bmain, old_id->lib, new_id);
}
}
@@ -326,7 +331,7 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c
if (lib_local || is_local) {
if (!is_lib) {
id_clear_lib_data_ex(bmain, id, id_in_mainlist);
- BKE_id_expand_local(id);
+ BKE_id_expand_local(bmain, id);
}
else {
ID *id_new;
@@ -1252,6 +1257,10 @@ void BKE_main_free(Main *mainvar)
}
}
+ if (mainvar->relations) {
+ BKE_main_relations_free(mainvar);
+ }
+
BLI_spin_end((SpinLock *)mainvar->lock);
MEM_freeN(mainvar->lock);
DEG_evaluation_context_free(mainvar->eval_ctx);
@@ -1268,6 +1277,78 @@ void BKE_main_unlock(struct Main *bmain)
BLI_spin_unlock((SpinLock *) bmain->lock);
}
+
+static int main_relations_create_cb(void *user_data, ID *id_self, ID **id_pointer, int cb_flag)
+{
+ MainIDRelations *rel = user_data;
+
+ if (*id_pointer) {
+ MainIDRelationsEntry *entry, **entry_p;
+
+ entry = BLI_mempool_alloc(rel->entry_pool);
+ if (BLI_ghash_ensure_p(rel->id_user_to_used, id_self, (void ***)&entry_p)) {
+ entry->next = *entry_p;
+ }
+ else {
+ entry->next = NULL;
+ }
+ entry->id_pointer = id_pointer;
+ entry->usage_flag = cb_flag;
+ *entry_p = entry;
+
+ entry = BLI_mempool_alloc(rel->entry_pool);
+ if (BLI_ghash_ensure_p(rel->id_used_to_user, *id_pointer, (void ***)&entry_p)) {
+ entry->next = *entry_p;
+ }
+ else {
+ entry->next = NULL;
+ }
+ entry->id_pointer = (ID **)id_self;
+ entry->usage_flag = cb_flag;
+ *entry_p = entry;
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+/** Generate the mappings between used IDs and their users, and vice-versa. */
+void BKE_main_relations_create(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ ID *id;
+ int a;
+
+ if (bmain->relations != NULL) {
+ BKE_main_relations_free(bmain);
+ }
+
+ bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__);
+ bmain->relations->id_used_to_user = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ bmain->relations->id_user_to_used = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ bmain->relations->entry_pool = BLI_mempool_create(sizeof(MainIDRelationsEntry), 128, 128, BLI_MEMPOOL_NOP);
+
+ for (a = set_listbasepointers(bmain, lbarray); a--; ) {
+ for (id = lbarray[a]->first; id; id = id->next) {
+ BKE_library_foreach_ID_link(NULL, id, main_relations_create_cb, bmain->relations, IDWALK_READONLY);
+ }
+ }
+}
+
+void BKE_main_relations_free(Main *bmain)
+{
+ if (bmain->relations) {
+ if (bmain->relations->id_used_to_user) {
+ BLI_ghash_free(bmain->relations->id_used_to_user, NULL, NULL);
+ }
+ if (bmain->relations->id_user_to_used) {
+ BLI_ghash_free(bmain->relations->id_user_to_used, NULL, NULL);
+ }
+ BLI_mempool_destroy(bmain->relations->entry_pool);
+ MEM_freeN(bmain->relations);
+ bmain->relations = NULL;
+ }
+}
+
/**
* Generates a raw .blend file thumbnail data from given image.
*
@@ -1623,6 +1704,53 @@ void BKE_main_id_clear_newpoins(Main *bmain)
}
}
+
+static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRelations *id_relations, GSet *done_ids)
+{
+ if (BLI_gset_haskey(done_ids, id)) {
+ return; /* Already checked, nothing else to do. */
+ }
+
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id);
+ BLI_gset_insert(loop_tags, id);
+ for (; entry != NULL; entry = entry->next) {
+ ID *par_id = (ID *)entry->id_pointer; /* used_to_user stores ID pointer, not pointer to ID pointer... */
+
+ /* Shapekeys are considered 'private' to their owner ID here, and never tagged (since they cannot be linked),
+ * so we have to switch effective parent to their owner. */
+ if (GS(par_id->name) == ID_KE) {
+ par_id = ((Key *)par_id)->from;
+ }
+
+ if (par_id->lib == NULL) {
+ /* Local user, early out to avoid some gset querying... */
+ continue;
+ }
+ if (!BLI_gset_haskey(done_ids, par_id)) {
+ if (BLI_gset_haskey(loop_tags, par_id)) {
+ /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it.
+ * Note that this is the situation that can lead to archipelagoes of linked data-blocks
+ * (since all of them have non-local users, they would all be duplicated, leading to a loop of unused
+ * linked data-blocks that cannot be freed since they all use each other...). */
+ continue;
+ }
+ /* Else, recursively check that user ID. */
+ library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids);
+ }
+
+ if (par_id->tag & LIB_TAG_DOIT) {
+ /* This user will be fully local in future, so far so good, nothing to do here but check next user. */
+ }
+ else {
+ /* This user won't be fully local in future, so current ID won't be either. And we are done checking it. */
+ id->tag &= ~LIB_TAG_DOIT;
+ break;
+ }
+ }
+ BLI_gset_add(done_ids, id);
+ BLI_gset_remove(loop_tags, id, NULL);
+}
+
/** Make linked datablocks local.
*
* \param bmain Almost certainly G.main.
@@ -1633,11 +1761,10 @@ void BKE_main_id_clear_newpoins(Main *bmain)
/* Note: Old (2.77) version was simply making (tagging) datablocks as local, without actually making any check whether
* they were also indirectly used or not...
*
- * Current version uses regular id_make_local callback, which is not super-efficient since this ends up
- * duplicating some IDs and then removing original ones (due to missing knowledge of which ID uses some other ID).
- *
- * However, we now have a first check that allows us to use 'direct localization' of a lot of IDs, so performances
- * are now *reasonably* OK.
+ * Current version uses regular id_make_local callback, with advanced pre-processing step to detect all cases of
+ * IDs currently indirectly used, but which will be used by local data only once this function is finished.
+ * This allows to avoid any uneeded duplication of IDs, and hence all time lost afterwards to remove
+ * orphaned linked data-blocks...
*/
void BKE_library_make_local(
Main *bmain, const Library *lib, GHash *old_to_new_ids, const bool untagged_only, const bool set_fake)
@@ -1648,9 +1775,12 @@ void BKE_library_make_local(
LinkNode *todo_ids = NULL;
LinkNode *copied_ids = NULL;
- LinkNode *linked_loop_candidates = NULL;
MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__);
+ BKE_main_relations_create(bmain);
+
+ GSet *done_ids = BLI_gset_ptr_new(__func__);
+
/* Step 1: Detect datablocks to make local. */
for (a = set_listbasepointers(bmain, lbarray); a--; ) {
id = lbarray[a]->first;
@@ -1660,16 +1790,25 @@ void BKE_library_make_local(
const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name)));
for (; id; id = id->next) {
+ ID *ntree = (ID *)ntreeFromID(id);
+
id->tag &= ~LIB_TAG_DOIT;
+ if (ntree != NULL) {
+ ntree->tag &= ~LIB_TAG_DOIT;
+ }
if (id->lib == NULL) {
id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
}
- /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so its
- * possible to tag data you don't want to be made local, used for
- * appending data, so any libdata already linked wont become local
- * (very nasty to discover all your links are lost after appending).
+ /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so its possible to tag data you don't want to
+ * be made local, used for appending data, so any libdata already linked wont become local (very nasty
+ * to discover all your links are lost after appending).
* Also, never ever make proxified objects local, would not make any sense. */
+ /* Some more notes:
+ * - Shapekeys are never tagged here (since they are not linkable).
+ * - Nodetrees used in materials etc. have to be tagged manually, since they do not exist in Main (!).
+ * This is ok-ish on 'make local' side of things (since those are handled by their 'owner' IDs),
+ * but complicates slightly the pre-processing of relations between IDs at step 2... */
else if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) &&
ELEM(lib, NULL, id->lib) &&
!(GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) &&
@@ -1677,13 +1816,32 @@ void BKE_library_make_local(
{
BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
id->tag |= LIB_TAG_DOIT;
+
+ /* Tag those nasty non-ID nodetrees, but do not add them to todo list, making them local is handled
+ * by 'owner' ID. This is needed for library_make_local_copying_check() to work OK at step 2. */
+ if (ntree != NULL) {
+ ntree->tag |= LIB_TAG_DOIT;
+ }
+ }
+ else {
+ /* Linked ID that we won't be making local (needed info for step 2, see below). */
+ BLI_gset_add(done_ids, id);
}
}
}
/* Step 2: Check which datablocks we can directly make local (because they are only used by already, or future,
- * local data), others will need to be duplicated and further processed later. */
- BKE_library_indirectly_used_data_tag_clear(bmain);
+ * local data), others will need to be duplicated. */
+ GSet *loop_tags = BLI_gset_ptr_new(__func__);
+ for (LinkNode *it = todo_ids; it; it = it->next) {
+ library_make_local_copying_check(it->link, loop_tags, bmain->relations, done_ids);
+ BLI_assert(BLI_gset_size(loop_tags) == 0);
+ }
+ BLI_gset_free(loop_tags, NULL);
+ BLI_gset_free(done_ids, NULL);
+
+ /* Next step will most likely add new IDs, better to get rid of this mapping now. */
+ BKE_main_relations_free(bmain);
/* Step 3: Make IDs local, either directly (quick and simple), or using generic process,
* which involves more complex checks and might instead create a local copy of original linked ID. */
@@ -1693,10 +1851,10 @@ void BKE_library_make_local(
if (id->tag & LIB_TAG_DOIT) {
/* We know all users of this object are local or will be made fully local, even if currently there are
- * some indirect usages. So instead of making a copy that se'll likely get rid of later, directly make
+ * some indirect usages. So instead of making a copy that we'll likely get rid of later, directly make
* that data block local. Saves a tremendous amount of time with complex scenes... */
id_clear_lib_data_ex(bmain, id, true);
- BKE_id_expand_local(id);
+ BKE_id_expand_local(bmain, id);
id->tag &= ~LIB_TAG_DOIT;
}
else {
@@ -1732,6 +1890,9 @@ void BKE_library_make_local(
/* Step 4: We have to remap local usages of old (linked) ID to new (local) id in a separated loop,
* as lbarray ordering is not enough to ensure us we did catch all dependencies
* (e.g. if making local a parent object before its child...). See T48907. */
+ /* TODO This is now the biggest step by far (in term of processing time). We may be able to gain here by
+ * using again main->relations mapping, but... this implies BKE_libblock_remap & co to be able to update
+ * main->relations on the fly. Have to think about it a bit more, and see whether new code is OK first, anyway. */
for (LinkNode *it = copied_ids; it; it = it->next) {
id = it->link;
@@ -1750,6 +1911,53 @@ void BKE_library_make_local(
}
}
+ /* Note: Keeping both version of the code (old one being safer, since it still has checks against unused IDs)
+ * for now, we can remove old one once it has been tested for some time in master... */
+#if 1
+ /* Step 5: proxy 'remapping' hack. */
+ for (LinkNode *it = copied_ids; it; it = it->next) {
+ /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
+ * from another blend file into this one, even when that blend file contains proxified
+ * armatures that have local references. Since the proxified object needs to be linked
+ * (not local), this will only work when the "Localize all" checkbox is disabled.
+ * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
+ if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
+ Object *ob = (Object *)id;
+ Object *ob_new = (Object *)id->newid;
+ bool is_local = false, is_lib = false;
+
+ /* Proxies only work when the proxified object is linked-in from a library. */
+ if (ob->proxy->id.lib == NULL) {
+ printf("Warning, proxy object %s will loose its link to %s, because the "
+ "proxified object is local.\n", id->newid->name, ob->proxy->id.name);
+ continue;
+ }
+
+ BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
+
+ /* We can only switch the proxy'ing to a made-local proxy if it is no longer
+ * referred to from a library. Not checking for local use; if new local proxy
+ * was not used locally would be a nasty bug! */
+ if (is_local || is_lib) {
+ printf("Warning, made-local proxy object %s will loose its link to %s, "
+ "because the linked-in proxy is referenced (is_local=%i, is_lib=%i).\n",
+ id->newid->name, ob->proxy->id.name, is_local, is_lib);
+ }
+ else {
+ /* we can switch the proxy'ing from the linked-in to the made-local proxy.
+ * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
+ * was already allocated by BKE_object_make_local_ex() (which called BKE_object_copy_ex). */
+ ob_new->proxy = ob->proxy;
+ ob_new->proxy_group = ob->proxy_group;
+ ob_new->proxy_from = ob->proxy_from;
+ ob_new->proxy->proxy_from = ob_new;
+ ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
+ }
+ }
+ }
+#else
+ LinkNode *linked_loop_candidates = NULL;
+
/* Step 5: remove datablocks that have been copied to be localized and are no more used in the end...
* Note that we may have to loop more than once here, to tackle dependencies between linked objects... */
bool do_loop = true;
@@ -1800,6 +2008,8 @@ void BKE_library_make_local(
if (!is_local) {
if (!is_lib) { /* Not used at all, we can free it! */
+ BLI_assert(!"Unused linked data copy remaining from MakeLibLocal process, should not happen anymore");
+ printf("\t%s (from %s)\n", id->name, id->lib->id.name);
BKE_libblock_free(bmain, id);
it->link = NULL;
do_loop = true;
@@ -1813,7 +2023,7 @@ void BKE_library_make_local(
/* Grrrrrrr... those half-datablocks-stuff... grrrrrrrrrrr...
* Here we have to also tag them as potential candidates, otherwise they would falsy report
- * ID they used as 'directly used' in fourth step. */
+ * ID they used as 'directly used' in sixth step. */
ID *ntree = (ID *)ntreeFromID(id);
if (ntree != NULL) {
ntree->tag |= LIB_TAG_DOIT;
@@ -1838,6 +2048,7 @@ void BKE_library_make_local(
/* Note: in theory here we are only handling datablocks forming exclusive linked dependency-cycles-based
* archipelagos, so no need to check again after we have deleted one, as done in previous step. */
if (id->tag & LIB_TAG_DOIT) {
+ BLI_assert(!"Unused linked data copy remaining from MakeLibLocal process (archipelago case), should not happen anymore");
/* Object's deletion rely on valid ob->data, but ob->data may have already been freed here...
* Setting it to NULL may not be 100% correct, but should be safe and do the work. */
if (GS(id->name) == ID_OB) {
@@ -1858,6 +2069,7 @@ void BKE_library_make_local(
it->link = NULL;
}
}
+#endif
BKE_main_id_clear_newpoins(bmain);
BLI_memarena_free(linklist_mem);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index bfc26fcac0f..a071b3202be 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -63,10 +63,12 @@
#include "DNA_world_types.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_ghash.h"
#include "BLI_linklist_stack.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
#include "BKE_library.h"
@@ -83,11 +85,12 @@
#define FOREACH_FINALIZE _finalize
#define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0
-#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, cb_flag) \
+#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, _cb_flag) \
+ CHECK_TYPE(id_pp, ID **); \
if (!((_data)->status & IDWALK_STOP)) { \
const int _flag = (_data)->flag; \
ID *old_id = *(id_pp); \
- const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, cb_flag | (_data)->cd_flag); \
+ const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, _cb_flag | (_data)->cb_flag); \
if (_flag & IDWALK_READONLY) { \
BLI_assert(*(id_pp) == old_id); \
} \
@@ -128,7 +131,7 @@ enum {
typedef struct LibraryForeachIDData {
ID *self_id;
int flag;
- int cd_flag;
+ int cb_flag;
LibraryIDLinkCallback callback;
void *user_data;
int status;
@@ -139,19 +142,19 @@ typedef struct LibraryForeachIDData {
} LibraryForeachIDData;
static void library_foreach_rigidbodyworldSceneLooper(
- struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cd_flag)
+ struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_modifiersForeachIDLink(
- void *user_data, Object *UNUSED(object), ID **id_pointer, int cd_flag)
+ void *user_data, Object *UNUSED(object), ID **id_pointer, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
@@ -160,44 +163,44 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID
bool is_reference, void *user_data)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- const int cd_flag = is_reference ? IDWALK_USER : IDWALK_NOP;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_particlesystemsObjectLooper(
- ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cd_flag)
+ ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_sensorsObjectLooper(
- bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cd_flag)
+ bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_controllersObjectLooper(
- bController *UNUSED(controller), ID **id_pointer, void *user_data, int cd_flag)
+ bController *UNUSED(controller), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_actuatorsObjectLooper(
- bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cd_flag)
+ bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
@@ -206,7 +209,7 @@ static void library_foreach_nla_strip(LibraryForeachIDData *data, NlaStrip *stri
{
NlaStrip *substrip;
- FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_CB_USER);
for (substrip = strip->strips.first; substrip; substrip = substrip->next) {
library_foreach_nla_strip(data, substrip);
@@ -229,14 +232,14 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *
/* only used targets */
DRIVER_TARGETS_USED_LOOPER(dvar)
{
- FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_NOP);
+ FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_CB_NOP);
}
DRIVER_TARGETS_LOOPER_END
}
}
- FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_USER);
- FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_CB_USER);
+ FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_CB_USER);
for (nla_track = adt->nla_tracks.first; nla_track; nla_track = nla_track->next) {
for (nla_strip = nla_track->strips.first; nla_strip; nla_strip = nla_strip->next) {
@@ -249,23 +252,28 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *
static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex)
{
- FOREACH_CALLBACK_INVOKE(data, mtex->object, IDWALK_NOP);
- FOREACH_CALLBACK_INVOKE(data, mtex->tex, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, mtex->object, IDWALK_CB_NOP);
+ FOREACH_CALLBACK_INVOKE(data, mtex->tex, IDWALK_CB_USER);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint)
{
- FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_USER);
- FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_CB_USER);
+ FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_CB_USER);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_ID_as_subdata_link(
- ID *id, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
+ ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
{
+ /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */
+ ID *id = *id_pp;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pp, IDWALK_CB_PRIVATE);
+ BLI_assert(id == *id_pp);
+
if (flag & IDWALK_RECURSE) {
/* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in IDWALK_RECURSE case is
* troublesome, see T49553. */
@@ -275,8 +283,10 @@ static void library_foreach_ID_as_subdata_link(
}
}
else {
- BKE_library_foreach_ID_link(id, callback, user_data, flag);
+ BKE_library_foreach_ID_link(NULL, id, callback, user_data, flag);
}
+
+ FOREACH_FINALIZE_VOID;
}
/**
@@ -284,7 +294,7 @@ static void library_foreach_ID_as_subdata_link(
*
* \note: May be extended to be recursive in the future.
*/
-void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
+void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
{
LibraryForeachIDData data;
int i;
@@ -312,9 +322,21 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
#define CALLBACK_INVOKE(check_id_super, cb_flag) \
FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag)
- do {
+ for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) {
data.self_id = id;
- data.cd_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_INDIRECT_USAGE : 0;
+ data.cb_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_CB_INDIRECT_USAGE : 0;
+
+ if (bmain != NULL && bmain->relations != NULL && (flag & IDWALK_READONLY)) {
+ /* Note that this is minor optimization, even in worst cases (like id being an object with lots of
+ * drivers and constraints and modifiers, or material etc. with huge node tree),
+ * but we might as well use it (Main->relations is always assumed valid, it's responsability of code
+ * creating it to free it, especially if/when it starts modifying Main database). */
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id);
+ for (; entry != NULL; entry = entry->next) {
+ FOREACH_CALLBACK_INVOKE_ID_PP(&data, entry->id_pointer, entry->usage_flag);
+ }
+ continue;
+ }
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
@@ -325,7 +347,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_LI:
{
Library *lib = (Library *) id;
- CALLBACK_INVOKE(lib->parent, IDWALK_NOP);
+ CALLBACK_INVOKE(lib->parent, IDWALK_CB_NOP);
break;
}
case ID_SCE:
@@ -333,41 +355,41 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Scene *scene = (Scene *) id;
ToolSettings *toolsett = scene->toolsettings;
SceneRenderLayer *srl;
- Base *base;
+ BaseLegacy *legacy_base;
- CALLBACK_INVOKE(scene->camera, IDWALK_NOP);
- CALLBACK_INVOKE(scene->world, IDWALK_USER);
- CALLBACK_INVOKE(scene->set, IDWALK_NOP);
- CALLBACK_INVOKE(scene->clip, IDWALK_USER);
+ CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(scene->world, IDWALK_CB_USER);
+ CALLBACK_INVOKE(scene->set, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(scene->clip, IDWALK_CB_USER);
if (scene->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)scene->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&scene->nodetree, callback, user_data, flag, &data);
}
/* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later,
* since basact is just a pointer to one of those items. */
- CALLBACK_INVOKE(scene->obedit, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->obedit, IDWALK_CB_NOP);
for (srl = scene->r.layers.first; srl; srl = srl->next) {
FreestyleModuleConfig *fmc;
FreestyleLineSet *fls;
if (srl->mat_override) {
- CALLBACK_INVOKE(srl->mat_override, IDWALK_USER);
+ CALLBACK_INVOKE(srl->mat_override, IDWALK_CB_USER);
}
if (srl->light_override) {
- CALLBACK_INVOKE(srl->light_override, IDWALK_USER);
+ CALLBACK_INVOKE(srl->light_override, IDWALK_CB_USER);
}
for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
if (fmc->script) {
- CALLBACK_INVOKE(fmc->script, IDWALK_NOP);
+ CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP);
}
}
for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
if (fls->group) {
- CALLBACK_INVOKE(fls->group, IDWALK_USER);
+ CALLBACK_INVOKE(fls->group, IDWALK_CB_USER);
}
if (fls->linestyle) {
- CALLBACK_INVOKE(fls->linestyle, IDWALK_USER);
+ CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER);
}
}
}
@@ -376,38 +398,59 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Sequence *seq;
SEQP_BEGIN(scene->ed, seq)
{
- CALLBACK_INVOKE(seq->scene, IDWALK_NOP);
- CALLBACK_INVOKE(seq->scene_camera, IDWALK_NOP);
- CALLBACK_INVOKE(seq->clip, IDWALK_USER);
- CALLBACK_INVOKE(seq->mask, IDWALK_USER);
- CALLBACK_INVOKE(seq->sound, IDWALK_USER);
+ CALLBACK_INVOKE(seq->scene, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(seq->scene_camera, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER);
+ CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER);
+ CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER);
for (SequenceModifierData *smd = seq->modifiers.first; smd; smd = smd->next) {
- CALLBACK_INVOKE(smd->mask_id, IDWALK_USER);
+ CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER);
}
}
SEQ_END
}
- CALLBACK_INVOKE(scene->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
+
+ for (legacy_base = scene->base.first; legacy_base; legacy_base = legacy_base->next) {
+ CALLBACK_INVOKE(legacy_base->object, IDWALK_CB_USER);
+ }
+
+ SceneCollection *sc;
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+ }
+
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
- for (base = scene->base.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_USER);
+ SceneLayer *sl;
+ for (sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ CALLBACK_INVOKE(base->object, IDWALK_NOP);
+ }
}
for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {
- CALLBACK_INVOKE(marker->camera, IDWALK_NOP);
+ CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP);
}
if (toolsett) {
- CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_CB_NOP);
+
+ CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(toolsett->particle.object, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_CB_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);
- CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_USER);
+ CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_CB_USER);
+ CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_CB_USER);
+ CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_CB_USER);
if (toolsett->vpaint) {
library_foreach_paint(&data, &toolsett->vpaint->paint);
@@ -417,7 +460,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (toolsett->sculpt) {
library_foreach_paint(&data, &toolsett->sculpt->paint);
- CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_CB_NOP);
}
if (toolsett->uvsculpt) {
library_foreach_paint(&data, &toolsett->uvsculpt->paint);
@@ -428,7 +471,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
BKE_rigidbody_world_id_loop(scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data);
}
- CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_CB_NOP);
break;
}
@@ -439,75 +482,75 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
ParticleSystem *psys;
/* Object is special, proxies make things hard... */
- const int data_cd_flag = data.cd_flag;
- const int proxy_cd_flag = (object->proxy || object->proxy_group) ? IDWALK_INDIRECT_USAGE : 0;
+ const int data_cb_flag = data.cb_flag;
+ const int proxy_cb_flag = (object->proxy || object->proxy_group) ? IDWALK_CB_INDIRECT_USAGE : 0;
/* object data special case */
- data.cd_flag |= proxy_cd_flag;
+ data.cb_flag |= proxy_cb_flag;
if (object->type == OB_EMPTY) {
/* empty can have NULL or Image */
- CALLBACK_INVOKE_ID(object->data, IDWALK_USER);
+ CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER);
}
else {
/* when set, this can't be NULL */
if (object->data) {
- CALLBACK_INVOKE_ID(object->data, IDWALK_USER | IDWALK_NEVER_NULL);
+ CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
}
}
- data.cd_flag = data_cd_flag;
+ data.cb_flag = data_cb_flag;
- CALLBACK_INVOKE(object->parent, IDWALK_NOP);
- CALLBACK_INVOKE(object->track, IDWALK_NOP);
+ CALLBACK_INVOKE(object->parent, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(object->track, IDWALK_CB_NOP);
/* object->proxy is refcounted, but not object->proxy_group... *sigh* */
- CALLBACK_INVOKE(object->proxy, IDWALK_USER);
- CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP);
+ CALLBACK_INVOKE(object->proxy, IDWALK_CB_USER);
+ CALLBACK_INVOKE(object->proxy_group, IDWALK_CB_NOP);
/* Special case!
* Since this field is set/owned by 'user' of this ID (and not ID itself), it is only indirect usage
* if proxy object is linked... Twisted. */
if (object->proxy_from) {
- data.cd_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_INDIRECT_USAGE : 0;
+ data.cb_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_CB_INDIRECT_USAGE : 0;
}
- CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP);
- data.cd_flag = data_cd_flag;
+ CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_NOP);
+ data.cb_flag = data_cb_flag;
- CALLBACK_INVOKE(object->poselib, IDWALK_USER);
+ CALLBACK_INVOKE(object->poselib, IDWALK_CB_USER);
- data.cd_flag |= proxy_cd_flag;
+ data.cb_flag |= proxy_cb_flag;
for (i = 0; i < object->totcol; i++) {
- CALLBACK_INVOKE(object->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(object->mat[i], IDWALK_CB_USER);
}
- data.cd_flag = data_cd_flag;
+ data.cb_flag = data_cb_flag;
- CALLBACK_INVOKE(object->gpd, IDWALK_USER);
- CALLBACK_INVOKE(object->dup_group, IDWALK_USER);
+ CALLBACK_INVOKE(object->gpd, IDWALK_CB_USER);
+ CALLBACK_INVOKE(object->dup_group, IDWALK_CB_USER);
if (object->pd) {
- CALLBACK_INVOKE(object->pd->tex, IDWALK_USER);
- CALLBACK_INVOKE(object->pd->f_source, IDWALK_NOP);
+ CALLBACK_INVOKE(object->pd->tex, IDWALK_CB_USER);
+ CALLBACK_INVOKE(object->pd->f_source, IDWALK_CB_NOP);
}
/* Note that ob->effect is deprecated, so no need to handle it here. */
if (object->pose) {
bPoseChannel *pchan;
- data.cd_flag |= proxy_cd_flag;
+ data.cb_flag |= proxy_cb_flag;
for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) {
- CALLBACK_INVOKE(pchan->custom, IDWALK_USER);
+ CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER);
BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data);
}
- data.cd_flag = data_cd_flag;
+ data.cb_flag = data_cb_flag;
}
if (object->rigidbody_constraint) {
- CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_NOP);
- CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_NOP);
+ CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_CB_NOP);
}
if (object->lodlevels.first) {
LodLevel *level;
for (level = object->lodlevels.first; level; level = level->next) {
- CALLBACK_INVOKE(level->source, IDWALK_NOP);
+ CALLBACK_INVOKE(level->source, IDWALK_CB_NOP);
}
}
@@ -519,10 +562,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (object->soft) {
- CALLBACK_INVOKE(object->soft->collision_group, IDWALK_NOP);
+ CALLBACK_INVOKE(object->soft->collision_group, IDWALK_CB_NOP);
if (object->soft->effector_weights) {
- CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_NOP);
+ CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_CB_NOP);
}
}
@@ -535,10 +578,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_ME:
{
Mesh *mesh = (Mesh *) id;
- CALLBACK_INVOKE(mesh->texcomesh, IDWALK_USER);
- CALLBACK_INVOKE(mesh->key, IDWALK_USER);
+ CALLBACK_INVOKE(mesh->texcomesh, IDWALK_CB_USER);
+ CALLBACK_INVOKE(mesh->key, IDWALK_CB_USER);
for (i = 0; i < mesh->totcol; i++) {
- CALLBACK_INVOKE(mesh->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER);
}
/* XXX Really not happy with this - probably texface should rather use some kind of
@@ -550,7 +593,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data;
for (int j = 0; j < mesh->totpoly; j++, txface++) {
- CALLBACK_INVOKE(txface->tpage, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(txface->tpage, IDWALK_CB_USER_ONE);
}
}
}
@@ -560,7 +603,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
MTFace *tface = (MTFace *)mesh->fdata.layers[i].data;
for (int j = 0; j < mesh->totface; j++, tface++) {
- CALLBACK_INVOKE(tface->tpage, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(tface->tpage, IDWALK_CB_USER_ONE);
}
}
}
@@ -571,17 +614,17 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_CU:
{
Curve *curve = (Curve *) id;
- CALLBACK_INVOKE(curve->bevobj, IDWALK_NOP);
- CALLBACK_INVOKE(curve->taperobj, IDWALK_NOP);
- CALLBACK_INVOKE(curve->textoncurve, IDWALK_NOP);
- CALLBACK_INVOKE(curve->key, IDWALK_USER);
+ CALLBACK_INVOKE(curve->bevobj, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(curve->taperobj, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(curve->textoncurve, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(curve->key, IDWALK_CB_USER);
for (i = 0; i < curve->totcol; i++) {
- CALLBACK_INVOKE(curve->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(curve->mat[i], IDWALK_CB_USER);
}
- CALLBACK_INVOKE(curve->vfont, IDWALK_USER);
- CALLBACK_INVOKE(curve->vfontb, IDWALK_USER);
- CALLBACK_INVOKE(curve->vfonti, IDWALK_USER);
- CALLBACK_INVOKE(curve->vfontbi, IDWALK_USER);
+ CALLBACK_INVOKE(curve->vfont, IDWALK_CB_USER);
+ CALLBACK_INVOKE(curve->vfontb, IDWALK_CB_USER);
+ CALLBACK_INVOKE(curve->vfonti, IDWALK_CB_USER);
+ CALLBACK_INVOKE(curve->vfontbi, IDWALK_CB_USER);
break;
}
@@ -589,7 +632,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
MetaBall *metaball = (MetaBall *) id;
for (i = 0; i < metaball->totcol; i++) {
- CALLBACK_INVOKE(metaball->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(metaball->mat[i], IDWALK_CB_USER);
}
break;
}
@@ -604,9 +647,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (material->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)material->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data);
}
- CALLBACK_INVOKE(material->group, IDWALK_USER);
+ CALLBACK_INVOKE(material->group, IDWALK_CB_USER);
break;
}
@@ -615,26 +658,26 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Tex *texture = (Tex *) id;
if (texture->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)texture->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&texture->nodetree, callback, user_data, flag, &data);
}
- CALLBACK_INVOKE(texture->ima, IDWALK_USER);
+ CALLBACK_INVOKE(texture->ima, IDWALK_CB_USER);
if (texture->env) {
- CALLBACK_INVOKE(texture->env->object, IDWALK_NOP);
- CALLBACK_INVOKE(texture->env->ima, IDWALK_USER);
+ CALLBACK_INVOKE(texture->env->object, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(texture->env->ima, IDWALK_CB_USER);
}
if (texture->pd)
- CALLBACK_INVOKE(texture->pd->object, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->pd->object, IDWALK_CB_NOP);
if (texture->vd)
- CALLBACK_INVOKE(texture->vd->object, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->vd->object, IDWALK_CB_NOP);
if (texture->ot)
- CALLBACK_INVOKE(texture->ot->object, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->ot->object, IDWALK_CB_NOP);
break;
}
case ID_LT:
{
Lattice *lattice = (Lattice *) id;
- CALLBACK_INVOKE(lattice->key, IDWALK_USER);
+ CALLBACK_INVOKE(lattice->key, IDWALK_CB_USER);
break;
}
@@ -648,7 +691,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (lamp->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)lamp->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&lamp->nodetree, callback, user_data, flag, &data);
}
break;
}
@@ -656,7 +699,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_CA:
{
Camera *camera = (Camera *) id;
- CALLBACK_INVOKE(camera->dof_ob, IDWALK_NOP);
+ CALLBACK_INVOKE(camera->dof_ob, IDWALK_CB_NOP);
break;
}
@@ -667,14 +710,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
* (see also foreach_libblock_id_users_callback).
*/
Key *key = (Key *) id;
- CALLBACK_INVOKE_ID(key->from, IDWALK_NOP);
+ CALLBACK_INVOKE_ID(key->from, IDWALK_CB_NOP);
break;
}
case ID_SCR:
{
bScreen *screen = (bScreen *) id;
- CALLBACK_INVOKE(screen->scene, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(screen->scene, IDWALK_CB_USER_ONE);
break;
}
@@ -688,7 +731,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (world->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)world->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&world->nodetree, callback, user_data, flag, &data);
}
break;
}
@@ -696,7 +739,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_SPK:
{
Speaker *speaker = (Speaker *) id;
- CALLBACK_INVOKE(speaker->sound, IDWALK_USER);
+ CALLBACK_INVOKE(speaker->sound, IDWALK_CB_USER);
break;
}
@@ -705,7 +748,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Group *group = (Group *) id;
GroupObject *gob;
for (gob = group->gobject.first; gob; gob = gob->next) {
- CALLBACK_INVOKE(gob->ob, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(gob->ob, IDWALK_CB_USER_ONE);
}
break;
}
@@ -714,9 +757,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
bNodeTree *ntree = (bNodeTree *) id;
bNode *node;
- CALLBACK_INVOKE(ntree->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER);
for (node = ntree->nodes.first; node; node = node->next) {
- CALLBACK_INVOKE_ID(node->id, IDWALK_USER);
+ CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER);
}
break;
}
@@ -724,9 +767,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_BR:
{
Brush *brush = (Brush *) id;
- CALLBACK_INVOKE(brush->toggle_brush, IDWALK_NOP);
- CALLBACK_INVOKE(brush->clone.image, IDWALK_NOP);
- CALLBACK_INVOKE(brush->paint_curve, IDWALK_USER);
+ CALLBACK_INVOKE(brush->toggle_brush, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(brush->clone.image, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(brush->paint_curve, IDWALK_CB_USER);
library_foreach_mtex(&data, &brush->mtex);
library_foreach_mtex(&data, &brush->mask_mtex);
break;
@@ -735,10 +778,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
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);
+ CALLBACK_INVOKE(psett->dup_group, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(psett->dup_ob, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(psett->bb_ob, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(psett->collision_group, IDWALK_CB_NOP);
for (i = 0; i < MAX_MTEX; i++) {
if (psett->mtex[i]) {
@@ -747,16 +790,16 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (psett->effector_weights) {
- CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_CB_NOP);
}
if (psett->pd) {
- CALLBACK_INVOKE(psett->pd->tex, IDWALK_USER);
- CALLBACK_INVOKE(psett->pd->f_source, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->pd->tex, IDWALK_CB_USER);
+ CALLBACK_INVOKE(psett->pd->f_source, IDWALK_CB_NOP);
}
if (psett->pd2) {
- CALLBACK_INVOKE(psett->pd2->tex, IDWALK_USER);
- CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->pd2->tex, IDWALK_CB_USER);
+ CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_CB_NOP);
}
if (psett->boids) {
@@ -767,11 +810,11 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
for (rule = state->rules.first; rule; rule = rule->next) {
if (rule->type == eBoidRuleType_Avoid) {
BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- CALLBACK_INVOKE(gabr->ob, IDWALK_NOP);
+ CALLBACK_INVOKE(gabr->ob, IDWALK_CB_NOP);
}
else if (rule->type == eBoidRuleType_FollowLeader) {
BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- CALLBACK_INVOKE(flbr->ob, IDWALK_NOP);
+ CALLBACK_INVOKE(flbr->ob, IDWALK_CB_NOP);
}
}
}
@@ -787,19 +830,19 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
MovieTrackingTrack *track;
MovieTrackingPlaneTrack *plane_track;
- CALLBACK_INVOKE(clip->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(clip->gpd, IDWALK_CB_USER);
for (track = tracking->tracks.first; track; track = track->next) {
- CALLBACK_INVOKE(track->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER);
}
for (object = tracking->objects.first; object; object = object->next) {
for (track = object->tracks.first; track; track = track->next) {
- CALLBACK_INVOKE(track->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER);
}
}
for (plane_track = tracking->plane_tracks.first; plane_track; plane_track = plane_track->next) {
- CALLBACK_INVOKE(plane_track->image, IDWALK_USER);
+ CALLBACK_INVOKE(plane_track->image, IDWALK_CB_USER);
}
break;
}
@@ -814,7 +857,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
for (mask_spline = mask_layer->splines.first; mask_spline; mask_spline = mask_spline->next) {
for (i = 0; i < mask_spline->tot_point; i++) {
MaskSplinePoint *point = &mask_spline->points[i];
- CALLBACK_INVOKE_ID(point->parent.id, IDWALK_USER);
+ CALLBACK_INVOKE_ID(point->parent.id, IDWALK_CB_USER);
}
}
}
@@ -832,14 +875,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (linestyle->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)linestyle->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&linestyle->nodetree, callback, user_data, flag, &data);
}
for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) {
if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)lsm;
if (p->target) {
- CALLBACK_INVOKE(p->target, IDWALK_NOP);
+ CALLBACK_INVOKE(p->target, IDWALK_CB_NOP);
}
}
}
@@ -847,7 +890,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)lsm;
if (p->target) {
- CALLBACK_INVOKE(p->target, IDWALK_NOP);
+ CALLBACK_INVOKE(p->target, IDWALK_CB_NOP);
}
}
}
@@ -855,7 +898,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)lsm;
if (p->target) {
- CALLBACK_INVOKE(p->target, IDWALK_NOP);
+ CALLBACK_INVOKE(p->target, IDWALK_CB_NOP);
}
}
}
@@ -866,7 +909,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
bAction *act = (bAction *) id;
for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
- CALLBACK_INVOKE(marker->camera, IDWALK_NOP);
+ CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP);
}
break;
}
@@ -889,7 +932,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
break;
}
- } while ((id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL));
+ }
FOREACH_FINALIZE:
if (data.ids_handled) {
@@ -907,13 +950,13 @@ FOREACH_FINALIZE:
/**
* re-usable function, use when replacing ID's
*/
-void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag)
+void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
{
- if (cd_flag & IDWALK_USER) {
+ if (cb_flag & IDWALK_CB_USER) {
id_us_min(id_src);
id_us_plus(id_dst);
}
- else if (cd_flag & IDWALK_USER_ONE) {
+ else if (cb_flag & IDWALK_CB_USER_ONE) {
id_us_ensure_real(id_dst);
}
}
@@ -943,7 +986,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_TXT, ID_SO, ID_MC, ID_IM, ID_AC
+ ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_PA, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC
/* + constraints, modifiers and game logic ID types... */);
#else
return true;
@@ -1047,7 +1090,7 @@ static int foreach_libblock_id_users_callback(void *user_data, ID *self_id, ID *
(iter->id->tag & LIB_TAG_EXTRAUSER) ? 1 : 0, (iter->id->tag & LIB_TAG_EXTRAUSER_SET) ? 1 : 0,
(cb_flag & IDWALK_INDIRECT_USAGE) ? 1 : 0);
#endif
- if (cb_flag & IDWALK_INDIRECT_USAGE) {
+ if (cb_flag & IDWALK_CB_INDIRECT_USAGE) {
iter->count_indirect++;
}
else {
@@ -1078,7 +1121,7 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
iter.curr_id = id_user;
iter.count_direct = iter.count_indirect = 0;
- BKE_library_foreach_ID_link(iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_NOP);
+ BKE_library_foreach_ID_link(NULL, iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_READONLY);
return iter.count_direct + iter.count_indirect;
}
@@ -1107,7 +1150,7 @@ static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
}
iter.curr_id = id_curr;
BKE_library_foreach_ID_link(
- id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+ bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
is_defined = ((check_linked ? iter.count_indirect : iter.count_direct) != 0);
}
@@ -1158,7 +1201,7 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo
continue;
}
iter.curr_id = id_curr;
- BKE_library_foreach_ID_link(id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+ BKE_library_foreach_ID_link(bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
is_defined = (iter.count_direct != 0 && iter.count_indirect != 0);
}
@@ -1235,7 +1278,8 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
/* Unused ID (so far), no need to check it further. */
continue;
}
- BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP);
+ BKE_library_foreach_ID_link(
+ bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
}
}
}
@@ -1262,7 +1306,8 @@ void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
/* Local or non-indirectly-used ID (so far), no need to check it further. */
continue;
}
- BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP);
+ BKE_library_foreach_ID_link(
+ bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
}
}
}
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index d7d566a9ec0..9946d1cc81f 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -71,6 +71,7 @@
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
@@ -158,6 +159,10 @@ enum {
static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id_p, int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
IDRemap *id_remap_data = user_data;
ID *old_id = id_remap_data->old_id;
ID *new_id = id_remap_data->new_id;
@@ -169,14 +174,14 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
}
if (*id_p && (*id_p == old_id)) {
- const bool is_indirect = (cb_flag & IDWALK_INDIRECT_USAGE) != 0;
+ const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
/* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
* on the other hand since they get reset to lib data on file open/reload it is indirect too...
* Edit Mode is also a 'skip direct' case. */
const bool is_obj = (GS(id->name) == ID_OB);
const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
- const bool is_never_null = ((cb_flag & IDWALK_NEVER_NULL) && (new_id == NULL) &&
+ const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
(id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
@@ -185,7 +190,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
id->name, old_id->name, old_id, new_id ? new_id->name : "<NONE>", new_id, skip_indirect);
#endif
- if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_NEVER_NULL)) {
+ if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) {
id->tag |= LIB_TAG_DOIT;
}
@@ -203,10 +208,10 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
else {
BLI_assert(0);
}
- if (cb_flag & IDWALK_USER) {
+ if (cb_flag & IDWALK_CB_USER) {
id_remap_data->skipped_refcounted++;
}
- else if (cb_flag & IDWALK_USER_ONE) {
+ else if (cb_flag & IDWALK_CB_USER_ONE) {
/* No need to count number of times this happens, just a flag is enough. */
id_remap_data->status |= ID_REMAP_IS_USER_ONE_SKIPPED;
}
@@ -216,13 +221,13 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
*id_p = new_id;
DAG_id_tag_update_ex(id_remap_data->bmain, id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
- if (cb_flag & IDWALK_USER) {
+ if (cb_flag & IDWALK_CB_USER) {
id_us_min(old_id);
/* We do not want to handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */
if (new_id)
new_id->us++;
}
- else if (cb_flag & IDWALK_USER_ONE) {
+ else if (cb_flag & IDWALK_CB_USER_ONE) {
id_us_ensure_real(new_id);
/* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET) are assumed to be set as needed,
* that extra user is processed in final handling... */
@@ -238,7 +243,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
/* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */
static void libblock_remap_data_preprocess_scene_base_unlink(
- IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect)
+ IDRemap *r_id_remap_data, Scene *sce, BaseLegacy *base, const bool skip_indirect, const bool is_indirect)
{
if (skip_indirect && is_indirect) {
r_id_remap_data->skipped_indirect++;
@@ -254,6 +259,22 @@ static void libblock_remap_data_preprocess_scene_base_unlink(
}
}
+/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */
+static void libblock_remap_data_preprocess_scene_object_unlink(
+ IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect)
+{
+ if (skip_indirect && is_indirect) {
+ r_id_remap_data->skipped_indirect++;
+ r_id_remap_data->skipped_refcounted++;
+ }
+ else {
+ BKE_collections_object_remove(r_id_remap_data->bmain, sce, ob, false);
+ if (!is_indirect) {
+ r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
+ }
+ }
+}
+
static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
{
switch (GS(r_id_remap_data->id->name)) {
@@ -268,7 +289,16 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
/* ... everything from scene. */
- Base *base, *base_next;
+ Object *ob_iter;
+ FOREACH_SCENE_OBJECT(sce, ob_iter)
+ {
+ libblock_remap_data_preprocess_scene_object_unlink(
+ r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
+ }
+ FOREACH_SCENE_OBJECT_END
+
+
+ BaseLegacy *base, *base_next;
for (base = sce->base.first; base; base = base_next) {
base_next = base->next;
libblock_remap_data_preprocess_scene_base_unlink(
@@ -278,8 +308,11 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
else if (GS(r_id_remap_data->old_id->name) == ID_OB) {
/* ... a specific object from scene. */
Object *old_ob = (Object *)r_id_remap_data->old_id;
- Base *base = BKE_scene_base_find(sce, old_ob);
+ libblock_remap_data_preprocess_scene_object_unlink(
+ r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
+
+ BaseLegacy *base = BKE_scene_base_find(sce, old_ob);
if (base) {
libblock_remap_data_preprocess_scene_base_unlink(
r_id_remap_data, sce, base, skip_indirect, is_indirect);
@@ -325,7 +358,7 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain,
}
if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */
for (Group *group = bmain->group.first; group; group = group->id.next) {
- BKE_group_object_unlink(group, NULL, NULL, NULL);
+ BKE_group_object_unlink(group, NULL);
}
}
else {
@@ -338,23 +371,17 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
{
/* Note that here we assume no object has no base (i.e. all objects are assumed instanced
* in one scene...). */
- for (Base *base = sce->base.first; base; base = base->next) {
- if (base->flag & OB_FROMGROUP) {
- Object *ob = base->object;
-
- if (ob->flag & OB_FROMGROUP) {
- Group *grp = BKE_group_object_find(NULL, ob);
-
- /* Unlinked group (old_id) is still in bmain... */
- if (grp && (&grp->id == old_id || grp->id.us == 0)) {
- grp = BKE_group_object_find(grp, ob);
- }
- if (!grp) {
- ob->flag &= ~OB_FROMGROUP;
- }
+ for (BaseLegacy *base = sce->base.first; base; base = base->next) {
+ Object *ob = base->object;
+ if (ob->flag & OB_FROMGROUP) {
+ Group *grp = BKE_group_object_find(NULL, ob);
+
+ /* Unlinked group (old_id) is still in bmain... */
+ if (grp && (&grp->id == old_id || grp->id.us == 0)) {
+ grp = BKE_group_object_find(grp, ob);
}
- if (!(ob->flag & OB_FROMGROUP)) {
- base->flag &= ~OB_FROMGROUP;
+ if (!grp) {
+ ob->flag &= ~OB_FROMGROUP;
}
}
}
@@ -434,7 +461,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
#endif
r_id_remap_data->id = id;
libblock_remap_data_preprocess(r_id_remap_data);
- BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
}
else {
i = set_listbasepointers(bmain, lb_array);
@@ -456,7 +483,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
r_id_remap_data->id = id_curr;
libblock_remap_data_preprocess(r_id_remap_data);
BKE_library_foreach_ID_link(
- id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
}
}
}
@@ -685,13 +712,17 @@ void BKE_libblock_relink_ex(
}
}
-static int id_relink_to_newid_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cd_flag)
+static int id_relink_to_newid_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
ID *id = *id_pointer;
if (id) {
/* See: NEW_ID macro */
if (id->newid) {
- BKE_library_update_ID_link_user(id->newid, id, cd_flag);
+ BKE_library_update_ID_link_user(id->newid, id, cb_flag);
*id_pointer = id->newid;
}
else if (id->tag & LIB_TAG_NEW) {
@@ -711,7 +742,7 @@ void BKE_libblock_relink_to_newid(ID *id)
if (ID_IS_LINKED_DATABLOCK(id))
return;
- BKE_library_foreach_ID_link(id, id_relink_to_newid_looper, NULL, 0);
+ BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
}
void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id)
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 54945242fe4..435504859a4 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -111,6 +111,12 @@ void BKE_material_free(Material *ma)
BKE_icon_id_delete((ID *)ma);
BKE_previewimg_free(&ma->preview);
+
+ for (MaterialEngineSettings *mes = ma->engines_settings.first; mes; mes = mes->next) {
+ if (mes->data)
+ MEM_SAFE_FREE(mes->data);
+ }
+ BLI_freelistN(&ma->engines_settings);
}
void BKE_material_init(Material *ma)
@@ -248,6 +254,8 @@ Material *BKE_material_copy(Main *bmain, Material *ma)
BLI_listbase_clear(&man->gpumaterial);
+ /* TODO Duplicate Engine Settings and set runtime to NULL */
+
BKE_id_copy_ensure_local(bmain, &ma->id, &man->id);
return man;
@@ -279,6 +287,8 @@ Material *localize_material(Material *ma)
man->nodetree = ntreeLocalize(ma->nodetree);
BLI_listbase_clear(&man->gpumaterial);
+
+ /* TODO Duplicate Engine Settings and set runtime to NULL */
return man;
}
@@ -1698,6 +1708,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false);
matcopybuf.preview = NULL;
BLI_listbase_clear(&matcopybuf.gpumaterial);
+ /* TODO Duplicate Engine Settings and set runtime to NULL */
matcopied = 1;
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 97033a9555d..2632acea58b 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -316,7 +316,7 @@ bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
void BKE_mball_properties_copy(Scene *scene, Object *active_object)
{
Scene *sce_iter = scene;
- Base *base;
+ BaseLegacy *base;
Object *ob;
MetaBall *active_mball = (MetaBall *)active_object->data;
int basisnr, obnr;
@@ -359,27 +359,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
*/
Object *BKE_mball_basis_find(Scene *scene, Object *basis)
{
- Scene *sce_iter = scene;
- Base *base;
- Object *ob, *bob = basis;
+ Object *bob = basis;
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
- SceneBaseIter iter;
- EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
- while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
- if (ob != bob) {
- BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
-
- /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
- if (STREQ(obname, basisname)) {
- if (obnr < basisnr) {
- basis = ob;
- basisnr = obnr;
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
+ if (ob != bob) {
+ BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
+
+ /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
+ if (STREQ(obname, basisname)) {
+ if (obnr < basisnr) {
+ basis = ob;
+ basisnr = obnr;
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 5c0b09f0ff0..144a885ffd4 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -1080,7 +1080,7 @@ static void polygonize(PROCESS *process)
static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
{
Scene *sce_iter = scene;
- Base *base;
+ BaseLegacy *base;
Object *bob;
MetaBall *mb;
const MetaElem *ml;
@@ -1102,7 +1102,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
zero_size = 0;
ml = NULL;
- if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
+ if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
mb = ob->data;
if (mb->editelems) ml = mb->editelems->first;
diff --git a/source/blender/blenkernel/intern/mesh_render.c b/source/blender/blenkernel/intern/mesh_render.c
index 4118208d32f..fd0f49810fb 100644
--- a/source/blender/blenkernel/intern/mesh_render.c
+++ b/source/blender/blenkernel/intern/mesh_render.c
@@ -47,7 +47,7 @@
/* Mesh Interface */
#define MESH_RENDER_FUNCTION(func_name) \
- if (me->edit_btmesh) { \
+ if (me->edit_btmesh && me->edit_btmesh->derivedFinal) { \
return mesh_bmesh_##func_name(me); \
} \
else { \
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 3f3b4896653..05422a01dbf 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3776,3 +3776,20 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
return true;
}
+
+/* -------------------------------------------------------------------- */
+/* NodeTree kernel functions */
+
+void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
+ if (node->custom1 == layer_index) {
+ node->custom1 = 0;
+ }
+ else if (node->custom1 > layer_index) {
+ node->custom1--;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 171c369b3b0..c0540192422 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -91,6 +91,7 @@
#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
+#include "BKE_layer.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -153,7 +154,7 @@ void BKE_object_workob_clear(Object *workob)
void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
{
- Base *base = scene->base.first;
+ BaseLegacy *base = scene->base.first;
while (base) {
if (base->object == ob) base->lay = ob->lay;
@@ -458,6 +459,11 @@ void BKE_object_free(Object *ob)
}
BKE_previewimg_free(&ob->preview);
+
+ if (ob->collection_settings) {
+ BKE_layer_collection_engine_settings_free(ob->collection_settings);
+ MEM_freeN(ob->collection_settings);
+ }
}
/* actual check for internal data, not context or flags */
@@ -677,23 +683,25 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
/* general add: to scene, with layer from area and default name */
/* creates minimum required data, but without vertices etc. */
Object *BKE_object_add(
- Main *bmain, Scene *scene,
+ Main *bmain, Scene *scene, SceneLayer *sl,
int type, const char *name)
{
Object *ob;
Base *base;
+ LayerCollection *lc;
ob = BKE_object_add_only_object(bmain, type, name);
ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
- ob->lay = scene->lay;
-
- base = BKE_scene_base_add(scene, ob);
- BKE_scene_base_deselect_all(scene);
- BKE_scene_base_select(scene, base);
- DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ lc = BKE_layer_collection_active(sl);
+ BKE_collection_object_add(scene, lc->scene_collection, ob);
+ base = BKE_scene_layer_base_find(sl, ob);
+ BKE_scene_layer_base_deselect_all(sl);
+ BKE_scene_layer_base_select(sl, base);
+
+ DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
return ob;
}
@@ -1204,7 +1212,7 @@ void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, con
if (lib_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &ob->id);
- BKE_id_expand_local(&ob->id);
+ BKE_id_expand_local(bmain, &ob->id);
if (clear_proxy) {
if (ob->proxy_from != NULL) {
ob->proxy_from->proxy = NULL;
@@ -2236,18 +2244,6 @@ void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3],
}
}
-void BKE_boundbox_scale(struct BoundBox *bb_dst, const struct BoundBox *bb_src, float scale)
-{
- float cent[3];
- BKE_boundbox_calc_center_aabb(bb_src, cent);
-
- for (int i = 0; i < ARRAY_SIZE(bb_dst->vec); i++) {
- bb_dst->vec[i][0] = ((bb_src->vec[i][0] - cent[0]) * scale) + cent[0];
- bb_dst->vec[i][1] = ((bb_src->vec[i][1] - cent[1]) * scale) + cent[1];
- bb_dst->vec[i][2] = ((bb_src->vec[i][2] - cent[2]) * scale) + cent[2];
- }
-}
-
/**
* Returns a BBox which each dimensions are at least epsilon.
* \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range.
@@ -2554,11 +2550,11 @@ void BKE_scene_foreach_display_point(
Scene *scene, View3D *v3d, const short flag,
void (*func_cb)(const float[3], void *), void *user_data)
{
- Base *base;
+ BaseLegacy *base;
Object *ob;
for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) {
+ if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag_legacy & flag) == flag) {
ob = base->object;
if ((ob->transflag & OB_DUPLI) == 0) {
@@ -2816,45 +2812,6 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc,
return 1;
}
-/*
- * Test a bounding box for ray intersection
- * assumes the ray is already local to the boundbox space
- */
-bool BKE_boundbox_ray_hit_check(
- const struct BoundBox *bb,
- const float ray_start[3], const float ray_normal[3],
- float *r_lambda)
-{
- const int triangle_indexes[12][3] = {
- {0, 1, 2}, {0, 2, 3},
- {3, 2, 6}, {3, 6, 7},
- {1, 2, 6}, {1, 6, 5},
- {5, 6, 7}, {4, 5, 7},
- {0, 3, 7}, {0, 4, 7},
- {0, 1, 5}, {0, 4, 5}};
-
- bool result = false;
- int i;
-
- for (i = 0; i < 12 && (!result || r_lambda); i++) {
- float lambda;
- int v1, v2, v3;
- v1 = triangle_indexes[i][0];
- v2 = triangle_indexes[i][1];
- v3 = triangle_indexes[i][2];
- if (isect_ray_tri_v3(ray_start, ray_normal, bb->vec[v1], bb->vec[v2], bb->vec[v3], &lambda, NULL) &&
- (!r_lambda || *r_lambda > lambda))
- {
- result = true;
- if (r_lambda) {
- *r_lambda = lambda;
- }
- }
- }
-
- return result;
-}
-
static int pc_cmp(const void *a, const void *b)
{
const LinkData *ad = a, *bd = b;
@@ -3402,7 +3359,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
{
LinkNode *links = NULL;
- Base *base;
+ BaseLegacy *base;
/* Remove markers from all objects */
for (base = scene->base.first; base; base = base->next) {
@@ -3446,7 +3403,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
/* child relationship */
if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
- Base *local_base;
+ BaseLegacy *local_base;
for (local_base = scene->base.first; local_base; local_base = local_base->next) {
if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) {
@@ -3492,18 +3449,11 @@ struct LinkNode *BKE_object_groups(Object *ob)
return group_linknode;
}
-void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+void BKE_object_groups_clear(Object *ob)
{
Group *group = NULL;
-
- BLI_assert((base == NULL) || (base->object == object));
-
- if (scene && base == NULL) {
- base = BKE_scene_base_find(scene, object);
- }
-
- while ((group = BKE_group_object_find(group, base->object))) {
- BKE_group_object_unlink(group, object, scene, base);
+ while ((group = BKE_group_object_find(group, ob))) {
+ BKE_group_object_unlink(group, ob);
}
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index e3b801b3193..26af1c48afb 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -241,7 +241,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
else {
unsigned int lay = ctx->scene->lay;
int baseid = 0;
- Base *base;
+ BaseLegacy *base;
for (base = ctx->scene->base.first; base; base = base->next, baseid++) {
Object *ob = base->object;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 1ea27558545..228ae6afaba 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -633,8 +633,9 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
data->childcachebufs.last = psys->childcachebufs.last;
data->totchildcache = psys->totchildcache;
- if (psmd->dm_final)
- data->dm = CDDM_copy(psmd->dm_final);
+ if (psmd->dm_final) {
+ data->dm = CDDM_copy_with_tessface(psmd->dm_final);
+ }
data->totdmvert = psmd->totdmvert;
data->totdmedge = psmd->totdmedge;
data->totdmface = psmd->totdmface;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index ee435051151..8531c7c9df9 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2896,7 +2896,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
- Base *base;
+ BaseLegacy *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)
@@ -4328,12 +4328,12 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
{
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);
+ func(psys, (ID **)&psys->part, userdata, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
+ func(psys, (ID **)&psys->target_ob, userdata, IDWALK_CB_NOP);
+ func(psys, (ID **)&psys->parent, userdata, IDWALK_CB_NOP);
for (pt = psys->targets.first; pt; pt = pt->next) {
- func(psys, (ID **)&pt->ob, userdata, IDWALK_NOP);
+ func(psys, (ID **)&pt->ob, userdata, IDWALK_CB_NOP);
}
/* Even though psys->part should never be NULL, this can happen as an exception during deletion.
@@ -4343,7 +4343,7 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
int p;
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
- func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_NOP);
+ func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_CB_NOP);
}
}
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 30eb8dcb287..c3f2107c5af 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3541,7 +3541,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
Main *bmain = baker->main;
Scene *scene = baker->scene;
Scene *sce_iter; /* SETLOOPER macro only */
- Base *base;
+ BaseLegacy *base;
ListBase pidlist;
PTCacheID *pid = &baker->pid;
PointCache *cache = NULL;
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 6f86c68dc07..73fe5ae6cb8 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -974,14 +974,14 @@ void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw)
void BKE_rigidbody_world_id_loop(RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata)
{
- func(rbw, (ID **)&rbw->group, userdata, IDWALK_NOP);
- func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_NOP);
- func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_NOP);
+ func(rbw, (ID **)&rbw->group, userdata, IDWALK_CB_NOP);
+ func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_CB_NOP);
+ func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_CB_NOP);
if (rbw->objects) {
int i;
for (i = 0; i < rbw->numbodies; i++) {
- func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_NOP);
+ func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_CB_NOP);
}
}
}
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index fa221348932..7920d8b5696 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -992,19 +992,19 @@ void BKE_sca_sensors_id_loop(ListBase *senslist, SCASensorIDFunc func, void *use
bSensor *sensor;
for (sensor = senslist->first; sensor; sensor = sensor->next) {
- func(sensor, (ID **)&sensor->ob, userdata, IDWALK_NOP);
+ func(sensor, (ID **)&sensor->ob, userdata, IDWALK_CB_NOP);
switch (sensor->type) {
case SENS_TOUCH: /* DEPRECATED */
{
bTouchSensor *ts = sensor->data;
- func(sensor, (ID **)&ts->ma, userdata, IDWALK_NOP);
+ func(sensor, (ID **)&ts->ma, userdata, IDWALK_CB_NOP);
break;
}
case SENS_MESSAGE:
{
bMessageSensor *ms = sensor->data;
- func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_NOP);
+ func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_CB_NOP);
break;
}
case SENS_ALWAYS:
@@ -1035,7 +1035,7 @@ void BKE_sca_controllers_id_loop(ListBase *contlist, SCAControllerIDFunc func, v
case CONT_PYTHON:
{
bPythonCont *pc = controller->data;
- func(controller, (ID **)&pc->text, userdata, IDWALK_NOP);
+ func(controller, (ID **)&pc->text, userdata, IDWALK_CB_NOP);
break;
}
case CONT_LOGIC_AND:
@@ -1056,89 +1056,89 @@ void BKE_sca_actuators_id_loop(ListBase *actlist, SCAActuatorIDFunc func, void *
bActuator *actuator;
for (actuator = actlist->first; actuator; actuator = actuator->next) {
- func(actuator, (ID **)&actuator->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&actuator->ob, userdata, IDWALK_CB_NOP);
switch (actuator->type) {
case ACT_ADD_OBJECT: /* DEPRECATED */
{
bAddObjectActuator *aoa = actuator->data;
- func(actuator, (ID **)&aoa->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&aoa->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_ACTION:
{
bActionActuator *aa = actuator->data;
- func(actuator, (ID **)&aa->act, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&aa->act, userdata, IDWALK_CB_NOP);
break;
}
case ACT_SOUND:
{
bSoundActuator *sa = actuator->data;
- func(actuator, (ID **)&sa->sound, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->sound, userdata, IDWALK_CB_NOP);
break;
}
case ACT_EDIT_OBJECT:
{
bEditObjectActuator *eoa = actuator->data;
- func(actuator, (ID **)&eoa->ob, userdata, IDWALK_NOP);
- func(actuator, (ID **)&eoa->me, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&eoa->ob, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&eoa->me, userdata, IDWALK_CB_NOP);
break;
}
case ACT_SCENE:
{
bSceneActuator *sa = actuator->data;
- func(actuator, (ID **)&sa->scene, userdata, IDWALK_NOP);
- func(actuator, (ID **)&sa->camera, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->scene, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&sa->camera, userdata, IDWALK_CB_NOP);
break;
}
case ACT_PROPERTY:
{
bPropertyActuator *pa = actuator->data;
- func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_OBJECT:
{
bObjectActuator *oa = actuator->data;
- func(actuator, (ID **)&oa->reference, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&oa->reference, userdata, IDWALK_CB_NOP);
break;
}
case ACT_CAMERA:
{
bCameraActuator *ca = actuator->data;
- func(actuator, (ID **)&ca->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&ca->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_MESSAGE:
{
bMessageActuator *ma = actuator->data;
- func(actuator, (ID **)&ma->toObject, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&ma->toObject, userdata, IDWALK_CB_NOP);
break;
}
case ACT_2DFILTER:
{
bTwoDFilterActuator *tdfa = actuator->data;
- func(actuator, (ID **)&tdfa->text, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&tdfa->text, userdata, IDWALK_CB_NOP);
break;
}
case ACT_PARENT:
{
bParentActuator *pa = actuator->data;
- func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_ARMATURE:
{
bArmatureActuator *aa = actuator->data;
- func(actuator, (ID **)&aa->target, userdata, IDWALK_NOP);
- func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&aa->target, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_CB_NOP);
break;
}
case ACT_STEERING:
{
bSteeringActuator *sa = actuator->data;
- func(actuator, (ID **)&sa->target, userdata, IDWALK_NOP);
- func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->target, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_CB_NOP);
break;
}
/* Note: some types seems to be non-implemented? ACT_LAMP, ACT_MATERIAL... */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index a1338b4ea10..dc81dac134b 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -67,6 +67,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_editmesh.h"
@@ -78,6 +79,7 @@
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -107,6 +109,7 @@
const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER";
const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME";
+const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY";
const char *RE_engine_id_CYCLES = "CYCLES";
void free_avicodecdata(AviCodecData *acd)
@@ -154,13 +157,66 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
+/* copy SceneCollection tree but keep pointing to the same objects */
+static void scene_collection_copy(SceneCollection *scn, SceneCollection *sc)
+{
+ BLI_duplicatelist(&scn->objects, &sc->objects);
+ for (LinkData *link = scn->objects.first; link; link = link->next) {
+ id_us_plus(link->data);
+ }
+
+ BLI_duplicatelist(&scn->filter_objects, &sc->filter_objects);
+ for (LinkData *link = scn->filter_objects.first; link; link = link->next) {
+ id_us_plus(link->data);
+ }
+
+ BLI_duplicatelist(&scn->scene_collections, &sc->scene_collections);
+ SceneCollection *nscn = scn->scene_collections.first; /* nested SceneCollection new */
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ scene_collection_copy(nscn, nsc);
+ nscn = nscn->next;
+ }
+}
+
+/* Find the equivalent SceneCollection in the new tree */
+static SceneCollection *scene_collection_from_new_tree(SceneCollection *sc_reference, SceneCollection *scn, SceneCollection *sc)
+{
+ if (sc == sc_reference) {
+ return scn;
+ }
+
+ SceneCollection *nscn = scn->scene_collections.first; /* nested master collection new */
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+
+ SceneCollection *found = scene_collection_from_new_tree(sc_reference, nscn, nsc);
+ if (found) {
+ return found;
+ }
+ nscn = nscn->next;
+ }
+ return NULL;
+}
+
+/* recreate the LayerCollection tree */
+static void layer_collections_recreate(SceneLayer *sl, ListBase *lb, SceneCollection *mcn, SceneCollection *mc)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+
+ SceneCollection *sc = scene_collection_from_new_tree(lc->scene_collection, mcn, mc);
+ BLI_assert(sc);
+
+ /* instead of syncronizing both trees we simply re-create it */
+ BKE_collection_link(sl, sc);
+ }
+}
+
Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
{
Scene *scen;
SceneRenderLayer *srl, *new_srl;
FreestyleLineSet *lineset;
ToolSettings *ts;
- Base *base, *obase;
+ BaseLegacy *legacy_base, *olegacy_base;
if (type == SCE_COPY_EMPTY) {
ListBase rl, rv;
@@ -214,14 +270,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
BKE_libblock_relink_ex(bmain, scen->nodetree, &sce->id, &scen->id, false);
}
- obase = sce->base.first;
- base = scen->base.first;
- while (base) {
- id_us_plus(&base->object->id);
- if (obase == sce->basact) scen->basact = base;
+ olegacy_base = sce->base.first;
+ legacy_base = scen->base.first;
+ while (legacy_base) {
+ id_us_plus(&legacy_base->object->id);
+ if (olegacy_base == sce->basact) scen->basact = legacy_base;
- obase = obase->next;
- base = base->next;
+ olegacy_base = olegacy_base->next;
+ legacy_base = legacy_base->next;
}
/* copy action and remove animation used by sequencer */
@@ -244,6 +300,36 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
}
new_srl = new_srl->next;
}
+
+ /* layers and collections */
+ scen->collection = MEM_dupallocN(sce->collection);
+ SceneCollection *mcn = BKE_collection_master(scen);
+ SceneCollection *mc = BKE_collection_master(sce);
+
+ /* recursively creates a new SceneCollection tree */
+ scene_collection_copy(mcn, mc);
+
+ BLI_duplicatelist(&scen->render_layers, &sce->render_layers);
+ SceneLayer *new_sl = scen->render_layers.first;
+ for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+
+ /* we start fresh with no overrides and no visibility flags set
+ * instead of syncing both trees we simply unlink and relink the scene collection */
+ BLI_listbase_clear(&new_sl->layer_collections);
+ BLI_listbase_clear(&new_sl->object_bases);
+ layer_collections_recreate(new_sl, &sl->layer_collections, mcn, mc);
+
+ if (sl->basact) {
+ Object *active_ob = sl->basact->object;
+ for (Base *base = new_sl->object_bases.first; base; base = base->next) {
+ if (base->object == active_ob) {
+ new_sl->basact = base;
+ break;
+ }
+ }
+ }
+ new_sl = new_sl->next;
+ }
}
/* copy color management settings */
@@ -471,6 +557,23 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
curvemapping_free_data(&sce->r.mblur_shutter_curve);
+
+ for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+ BKE_scene_layer_free(sl);
+ }
+ BLI_freelistN(&sce->render_layers);
+
+ /* Master Collection */
+ BKE_collection_master_free(sce);
+ MEM_freeN(sce->collection);
+ sce->collection = NULL;
+
+ /* Runtime Engine Data */
+ for (RenderEngineSettings *res = sce->engines_settings.first; res; res = res->next) {
+ if (res->data)
+ MEM_freeN(res->data);
+ }
+ BLI_freelistN(&sce->engines_settings);
}
void BKE_scene_init(Scene *sce)
@@ -820,6 +923,12 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->gpencil_v2d_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
+
+ /* Master Collection */
+ sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
+ BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
+
+ BKE_scene_layer_add(sce, "Render Layer");
}
Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -835,9 +944,9 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
return sce;
}
-Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
+BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
{
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
if (STREQ(base->object->id.name + 2, name)) {
@@ -848,9 +957,9 @@ Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
return base;
}
-Base *BKE_scene_base_find(Scene *scene, Object *ob)
+BaseLegacy *BKE_scene_base_find(Scene *scene, Object *ob)
{
- return BLI_findptr(&scene->base, ob, offsetof(Base, object));
+ return BLI_findptr(&scene->base, ob, offsetof(BaseLegacy, object));
}
/**
@@ -861,11 +970,10 @@ Base *BKE_scene_base_find(Scene *scene, Object *ob)
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
Scene *sce;
- Base *base;
+ BaseLegacy *base;
Object *ob;
Group *group;
GroupObject *go;
- int flag;
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
@@ -897,13 +1005,7 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
ob->lay = base->lay;
/* group patch... */
- base->flag &= ~(OB_FROMGROUP);
- flag = ob->flag & (OB_FROMGROUP);
- base->flag |= flag;
-
- /* not too nice... for recovering objects with lost data */
- //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE;
- ob->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
}
/* no full animation update, this to enable render code to work (render code calls own animation updates) */
}
@@ -924,7 +1026,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
- Scene **scene, int val, Base **base, Object **ob)
+ Scene **scene, int val, BaseLegacy **base, Object **ob)
{
bool run_again = true;
@@ -1006,7 +1108,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
}
/* handle dupli's */
if (iter->dupob) {
- (*base)->flag |= OB_FROMDUPLI;
+ (*base)->flag_legacy |= OB_FROMDUPLI;
*ob = iter->dupob->ob;
iter->phase = F_DUPLI;
@@ -1025,7 +1127,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
}
else if (iter->phase == F_DUPLI) {
iter->phase = F_SCENE;
- (*base)->flag &= ~OB_FROMDUPLI;
+ (*base)->flag_legacy &= ~OB_FROMDUPLI;
if (iter->dupli_refob) {
/* Restore last object's real matrix. */
@@ -1052,7 +1154,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
Object *BKE_scene_camera_find(Scene *sc)
{
- Base *base;
+ BaseLegacy *base;
for (base = sc->base.first; base; base = base->next)
if (base->object->type == OB_CAMERA)
@@ -1154,47 +1256,54 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
return best_marker ? best_marker->name : NULL;
}
+void BKE_scene_remove_rigidbody_object(Scene *scene, Object *ob)
+{
+ /* remove rigid body constraint from world before removing object */
+ if (ob->rigidbody_constraint)
+ BKE_rigidbody_remove_constraint(scene, ob);
+ /* remove rigid body object from world before removing object */
+ if (ob->rigidbody_object)
+ BKE_rigidbody_remove_object(scene, ob);
+}
-Base *BKE_scene_base_add(Scene *sce, Object *ob)
+BaseLegacy *BKE_scene_base_add(Scene *sce, Object *ob)
{
- Base *b = MEM_callocN(sizeof(*b), __func__);
+ BaseLegacy *b = MEM_callocN(sizeof(*b), __func__);
BLI_addhead(&sce->base, b);
b->object = ob;
- b->flag = ob->flag;
+ b->flag_legacy = ob->flag;
b->lay = ob->lay;
return b;
}
-void BKE_scene_base_unlink(Scene *sce, Base *base)
+void BKE_scene_base_unlink(Scene *sce, BaseLegacy *base)
{
- /* remove rigid body constraint from world before removing object */
- if (base->object->rigidbody_constraint)
- BKE_rigidbody_remove_constraint(sce, base->object);
- /* remove rigid body object from world before removing object */
- if (base->object->rigidbody_object)
- BKE_rigidbody_remove_object(sce, base->object);
-
+ BKE_scene_remove_rigidbody_object(sce, base->object);
+
BLI_remlink(&sce->base, base);
if (sce->basact == base)
sce->basact = NULL;
}
+/* deprecated, use BKE_scene_layer_base_deselect_all */
void BKE_scene_base_deselect_all(Scene *sce)
{
- Base *b;
+ BaseLegacy *b;
for (b = sce->base.first; b; b = b->next) {
- b->flag &= ~SELECT;
- b->object->flag = b->flag;
+ b->flag_legacy &= ~SELECT;
+ int flag = b->object->flag & (OB_FROMGROUP);
+ b->object->flag = b->flag_legacy;
+ b->object->flag |= flag;
}
}
-void BKE_scene_base_select(Scene *sce, Base *selbase)
+void BKE_scene_base_select(Scene *sce, BaseLegacy *selbase)
{
- selbase->flag |= SELECT;
- selbase->object->flag = selbase->flag;
+ selbase->flag_legacy |= SELECT;
+ selbase->object->flag = selbase->flag_legacy;
sce->basact = selbase;
}
@@ -1492,15 +1601,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
for (sce = bmain->scene.first; sce; sce = sce->id.next) {
if (sce->nodetree) {
- bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
- if (node->custom1 == act)
- node->custom1 = 0;
- else if (node->custom1 > act)
- node->custom1--;
- }
- }
+ BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
}
}
@@ -1588,7 +1689,7 @@ float get_render_aosss_error(const RenderData *r, float error)
}
/* helper function for the SETLOOPER macro */
-Base *_setlooper_base_step(Scene **sce_iter, Base *base)
+BaseLegacy *_setlooper_base_step(Scene **sce_iter, BaseLegacy *base)
{
if (base && base->next) {
/* common case, step to the next */
@@ -1596,12 +1697,12 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base)
}
else if (base == NULL && (*sce_iter)->base.first) {
/* first time looping, return the scenes first base */
- return (Base *)(*sce_iter)->base.first;
+ return (BaseLegacy *)(*sce_iter)->base.first;
}
else {
/* reached the end, get the next base in the set */
while ((*sce_iter = (*sce_iter)->set)) {
- base = (Base *)(*sce_iter)->base.first;
+ base = (BaseLegacy *)(*sce_iter)->base.first;
if (base) {
return base;
}
@@ -1646,23 +1747,55 @@ bool BKE_scene_uses_blender_game(const Scene *scene)
return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME);
}
-void BKE_scene_base_flag_to_objects(struct Scene *scene)
+void BKE_scene_base_flag_to_objects(SceneLayer *sl)
{
- Base *base = scene->base.first;
+ Base *base = sl->object_bases.first;
while (base) {
- base->object->flag = base->flag;
+ BKE_scene_object_base_flag_sync_from_base(base);
base = base->next;
}
}
-void BKE_scene_base_flag_from_objects(struct Scene *scene)
+void BKE_scene_base_flag_sync_from_base(BaseLegacy *base)
{
- Base *base = scene->base.first;
+ BKE_scene_object_base_flag_sync_from_base(base);
+}
- while (base) {
- base->flag = base->object->flag;
- base = base->next;
+void BKE_scene_base_flag_sync_from_object(BaseLegacy *base)
+{
+ BKE_scene_object_base_flag_sync_from_object(base);
+}
+
+void BKE_scene_object_base_flag_sync_from_base(Base *base)
+{
+ Object *ob = base->object;
+
+ /* keep the object only flags untouched */
+ int flag = ob->flag & OB_FROMGROUP;
+
+ ob->flag = base->flag;
+ ob->flag |= flag;
+
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ob->flag |= SELECT;
+ }
+ else {
+ ob->flag &= ~SELECT;
+ }
+}
+
+void BKE_scene_object_base_flag_sync_from_object(Base *base)
+{
+ Object *ob = base->object;
+ base->flag = ob->flag;
+
+ if ((ob->flag & SELECT) != 0) {
+ base->flag |= BASE_SELECTED;
+ BLI_assert((base->flag & BASE_SELECTABLED) != 0);
+ }
+ else {
+ base->flag &= ~BASE_SELECTED;
}
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 1d2f5aee440..6a491ba5ec4 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -480,55 +480,74 @@ void BKE_sequencer_editing_free(Scene *scene)
static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf)
{
- if (ibuf->rect_float) {
+ if (ibuf->rect != NULL) {
+ IMB_colormanagement_assign_rect_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
+ }
+ if (ibuf->rect_float != NULL) {
IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
}
}
void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make_float)
{
- const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+ /* Early output check: if both buffers are NULL we have nothing to convert. */
+ if (ibuf->rect_float == NULL && ibuf->rect == NULL) {
+ return;
+ }
+ /* Get common conversion settings. */
const char *to_colorspace = scene->sequencer_colorspace_settings.name;
- const char *float_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
-
- if (!ibuf->rect_float) {
- if (ibuf->rect) {
- const char *byte_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
- if (make_float || !STREQ(to_colorspace, byte_colorspace)) {
- /* If byte space is not in sequencer's working space, we deliver float color space,
- * this is to to prevent data loss.
- */
-
- /* when converting byte buffer to float in sequencer we need to make float
- * buffer be in sequencer's working space, which is currently only doable
- * from linear space.
- */
-
- /*
- * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's
- */
-
- IMB_float_from_rect(ibuf);
- }
- else {
- return;
- }
+ /* Perform actual conversion logic. */
+ if (ibuf->rect_float == NULL) {
+ /* We are not requested to give float buffer and byte buffer is already
+ * in thee required colorspace. Can skip doing anything here.
+ */
+ const char *from_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
+ if (!make_float && STREQ(from_colorspace, to_colorspace)) {
+ return;
+ }
+ if (false) {
+ /* The idea here is to provide as fast playback as possible and
+ * enforcing float buffer here (a) uses more cache memory (b) might
+ * make some other effects slower to apply.
+ *
+ * However, this might also have negative effect by adding weird
+ * artifacts which will then not happen in final render.
+ */
+ IMB_colormanagement_transform_byte_threaded(
+ (unsigned char*)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace);
}
else {
- return;
+ /* We perform conversion to a float buffer so we don't worry about
+ * precision loss.
+ */
+ imb_addrectfloatImBuf(ibuf);
+ IMB_colormanagement_transform_from_byte_threaded(
+ ibuf->rect_float, (unsigned char*)ibuf->rect,
+ ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace);
+ /* We don't need byte buffer anymore. */
+ imb_freerectImBuf(ibuf);
}
}
-
- if (from_colorspace && from_colorspace[0] != '\0') {
- if (ibuf->rect)
+ else {
+ const char *from_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
+ /* Unknown input color space, can't perform conversion. */
+ if (from_colorspace == NULL || from_colorspace[0] == '\0') {
+ return;
+ }
+ /* We don't want both byte and float buffers around: they'll either run
+ * out of sync or conversion of byte buffer will loose precision in there.
+ */
+ if (ibuf->rect != NULL) {
imb_freerectImBuf(ibuf);
-
- if (!STREQ(float_colorspace, to_colorspace)) {
- IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, true);
- sequencer_imbuf_assign_spaces(scene, ibuf);
}
+ IMB_colormanagement_transform_threaded(ibuf->rect_float,
+ ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace,
+ true);
}
+ sequencer_imbuf_assign_spaces(scene, ibuf);
}
void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf)
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index d0ef5cfc092..f1ce69d3945 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -698,7 +698,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
static int get_lamp(Scene *scene, float *light)
{
- Base *base_tmp = NULL;
+ BaseLegacy *base_tmp = NULL;
int found_lamp = 0;
// try to find a lamp, preferably local
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 660107eb2e6..e7df1d810c9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -530,7 +530,7 @@ static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexo
}
}
else {
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
/*Only proceed for mesh object in same layer */
if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
ob= base->object;
@@ -576,7 +576,7 @@ static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertex
}
}
else {
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
/*Only proceed for mesh object in same layer */
if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
ob= base->object;
@@ -986,7 +986,7 @@ static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
}
}
else {
- for (Base *base = scene->base.first; base; base= base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base= base->next) {
if ( (base->lay & layer) && base->object->pd) {
if (base->object->pd->deflect)
return 1;
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 22288127119..fe4bcc738c6 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -147,12 +147,12 @@ void BKE_sound_free(bSound *sound)
BKE_sound_free_waveform(sound);
+#endif /* WITH_AUDASPACE */
if (sound->spinlock) {
BLI_spin_end(sound->spinlock);
MEM_freeN(sound->spinlock);
sound->spinlock = NULL;
- }
-#endif /* WITH_AUDASPACE */
+ }
}
void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local)
@@ -782,7 +782,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
{
Object *ob;
- Base *base;
+ BaseLegacy *base;
NlaTrack *track;
NlaStrip *strip;
Speaker *speaker;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 88575c7d3be..298790a9e9b 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1935,7 +1935,7 @@ void txt_do_undo(Text *text)
int op = text->undo_buf[text->undo_pos];
int prev_flags;
unsigned int linep;
- unsigned int uchar;
+ unsigned int uni_char;
unsigned int curln, selln;
unsigned short curc, selc;
unsigned short charp;
@@ -1971,14 +1971,14 @@ void txt_do_undo(Text *text)
case UNDO_BS_3:
case UNDO_BS_4:
charp = op - UNDO_BS_1 + 1;
- uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
/* get and restore the cursors */
txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uchar);
+ txt_add_char(text, uni_char);
text->undo_pos--;
break;
@@ -1988,14 +1988,14 @@ void txt_do_undo(Text *text)
case UNDO_DEL_3:
case UNDO_DEL_4:
charp = op - UNDO_DEL_1 + 1;
- uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
/* get and restore the cursors */
txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uchar);
+ txt_add_char(text, uni_char);
txt_move_left(text, 0);
@@ -2163,7 +2163,7 @@ void txt_do_redo(Text *text)
char *buf;
unsigned int linep;
unsigned short charp;
- unsigned int uchar;
+ unsigned int uni_uchar;
unsigned int curln, selln;
unsigned short curc, selc;
@@ -2190,9 +2190,9 @@ void txt_do_redo(Text *text)
txt_move_to(text, curln, curc, 1);
charp = op - UNDO_INSERT_1 + 1;
- uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp);
- txt_add_char(text, uchar);
+ txt_add_char(text, uni_uchar);
break;
case UNDO_BS_1:
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 2d3ecad19ad..60990c03b0e 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -1485,9 +1485,11 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture)
/* ------------------------------------------------------------------------- */
-void BKE_texture_get_value(
+void BKE_texture_get_value_ex(
const Scene *scene, Tex *texture,
- float *tex_co, TexResult *texres, bool use_color_management)
+ float *tex_co, TexResult *texres,
+ struct ImagePool *pool,
+ bool use_color_management)
{
int result_type;
bool do_color_manage = false;
@@ -1497,7 +1499,7 @@ void BKE_texture_get_value(
}
/* no node textures for now */
- result_type = multitex_ext_safe(texture, tex_co, texres, NULL, do_color_manage, false);
+ result_type = multitex_ext_safe(texture, tex_co, texres, pool, do_color_manage, false);
/* if the texture gave an RGB value, we assume it didn't give a valid
* intensity, since this is in the context of modifiers don't use perceptual color conversion.
@@ -1510,3 +1512,10 @@ void BKE_texture_get_value(
copy_v3_fl(&texres->tr, texres->tin);
}
}
+
+void BKE_texture_get_value(
+ const Scene *scene, Tex *texture,
+ float *tex_co, TexResult *texres, bool use_color_management)
+{
+ BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management);
+}
diff --git a/source/blender/blenlib/BLI_dynlib.h b/source/blender/blenlib/BLI_dynlib.h
index 7d5eb888021..310db9ea051 100644
--- a/source/blender/blenlib/BLI_dynlib.h
+++ b/source/blender/blenlib/BLI_dynlib.h
@@ -34,7 +34,7 @@
typedef struct DynamicLibrary DynamicLibrary;
-DynamicLibrary *BLI_dynlib_open(char *name);
+DynamicLibrary *BLI_dynlib_open(const char *name);
void *BLI_dynlib_find_symbol(DynamicLibrary *lib, const char *symname);
char *BLI_dynlib_get_error_as_string(DynamicLibrary *lib);
void BLI_dynlib_close(DynamicLibrary *lib);
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 7e3a009ede8..068c188e336 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -32,6 +32,7 @@
* \ingroup bli
*/
+#include "BLI_blenlib.h"
#include "BLI_sys_types.h" /* for bool */
#include "BLI_compiler_attrs.h"
diff --git a/source/blender/blenlib/BLI_iterator.h b/source/blender/blenlib/BLI_iterator.h
new file mode 100644
index 00000000000..d154b81ac82
--- /dev/null
+++ b/source/blender/blenlib/BLI_iterator.h
@@ -0,0 +1,54 @@
+/*
+ * ***** 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): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_ITERATOR_H__
+#define __BLI_ITERATOR_H__
+
+/** \file BLI_iterator.h
+ * \ingroup bli
+ */
+
+typedef struct Iterator {
+ void *current; /* current pointer we iterate over */
+ void *data; /* stored data required for this iterator */
+ bool valid;
+} Iterator;
+
+typedef void (*IteratorCb)(Iterator *iter);
+typedef void (*IteratorBeginCb)(Iterator *iter, void *data_in);
+
+#define ITER_BEGIN(callback_begin, callback_next, callback_end, _data_in, _type, _data_out) \
+{ \
+ IteratorCb callback_end_func = callback_end; \
+ Iterator iter_macro; \
+ for (callback_begin(&iter_macro, _data_in); \
+ iter_macro.valid; \
+ callback_next(&iter_macro)) \
+ { \
+ _data_out = (_type *) iter_macro.current;
+
+#define ITER_END \
+ } \
+ callback_end_func(&iter_macro); \
+}
+
+#endif /* __BLI_ITERATOR_H__ */
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index e3635be671f..4a85e859c16 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -293,6 +293,10 @@ void isect_ray_aabb_v3_precalc(
bool isect_ray_aabb_v3(
const struct IsectRayAABB_Precalc *data,
const float bb_min[3], const float bb_max[3], float *tmin);
+bool isect_ray_aabb_v3_simple(
+ const float orig[3], const float dir[3],
+ const float bb_min[3], const float bb_max[3],
+ float *tmin, float *tmax);
struct NearestRayToAABB_Precalc {
float ray_origin[3];
diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h
index 7929e1d6551..9d8222c575d 100644
--- a/source/blender/blenlib/BLI_sys_types.h
+++ b/source/blender/blenlib/BLI_sys_types.h
@@ -80,6 +80,11 @@ typedef uint64_t u_int64_t;
#include <stddef.h> /* size_t define */
#include <stdbool.h>
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned char uchar;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 3277519c66e..97225170f67 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -155,6 +155,7 @@ set(SRC
BLI_hash_md5.h
BLI_hash_mm2a.h
BLI_heap.h
+ BLI_iterator.h
BLI_jitter.h
BLI_kdopbvh.h
BLI_kdtree.h
diff --git a/source/blender/blenlib/PIL_time_utildefines.h b/source/blender/blenlib/PIL_time_utildefines.h
index 9157e04a7bf..412cfb3a090 100644
--- a/source/blender/blenlib/PIL_time_utildefines.h
+++ b/source/blender/blenlib/PIL_time_utildefines.h
@@ -80,9 +80,10 @@
} \
const float _delta_##var = TIMEIT_VALUE(var); \
_sum_##var += _delta_##var; \
+ _num_##var++; \
printf("time end (" #var "): %.6f" " " AT "\n", _delta_##var); \
- printf("time averaged (" #var "): %.6f" " " AT "\n", \
- (_sum_##var / ++_num_##var)); \
+ printf("time averaged (" #var "): %.6f (total: %.6f, in %d runs)\n", \
+ (_sum_##var / _num_##var), _sum_##var, (int)_num_##var); \
fflush(stdout); \
} (void)0
diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c
index b47c2ee60a6..51b91fb360f 100644
--- a/source/blender/blenlib/intern/dynlib.c
+++ b/source/blender/blenlib/intern/dynlib.c
@@ -50,7 +50,7 @@ struct DynamicLibrary {
#include "utf_winfunc.h"
#include "utfconv.h"
-DynamicLibrary *BLI_dynlib_open(char *name)
+DynamicLibrary *BLI_dynlib_open(const char *name)
{
DynamicLibrary *lib;
void *handle;
@@ -106,7 +106,7 @@ void BLI_dynlib_close(DynamicLibrary *lib)
#include <dlfcn.h>
-DynamicLibrary *BLI_dynlib_open(char *name)
+DynamicLibrary *BLI_dynlib_open(const char *name)
{
DynamicLibrary *lib;
void *handle = dlopen(name, RTLD_LAZY);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 8f5d84dfa08..aeb6a550cd9 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2309,6 +2309,34 @@ bool isect_ray_aabb_v3(
return true;
}
+/*
+ * Test a bounding box (AABB) for ray intersection
+ * assumes the ray is already local to the boundbox space
+ */
+bool isect_ray_aabb_v3_simple(
+ const float orig[3], const float dir[3],
+ const float bb_min[3], const float bb_max[3],
+ float *tmin, float *tmax)
+{
+ double t[7];
+ float hit_dist[2];
+ t[1] = (double)(bb_min[0] - orig[0]) / dir[0];
+ t[2] = (double)(bb_max[0] - orig[0]) / dir[0];
+ t[3] = (double)(bb_min[1] - orig[1]) / dir[1];
+ t[4] = (double)(bb_max[1] - orig[1]) / dir[1];
+ t[5] = (double)(bb_min[2] - orig[2]) / dir[2];
+ t[6] = (double)(bb_max[2] - orig[2]) / dir[2];
+ hit_dist[0] = (float)fmax(fmax(fmin(t[1], t[2]), fmin(t[3], t[4])), fmin(t[5], t[6]));
+ hit_dist[1] = (float)fmin(fmin(fmax(t[1], t[2]), fmax(t[3], t[4])), fmax(t[5], t[6]));
+ if ((hit_dist[1] < 0 || hit_dist[0] > hit_dist[1]))
+ return false;
+ else {
+ if (tmin) *tmin = hit_dist[0];
+ if (tmax) *tmax = hit_dist[1];
+ return true;
+ }
+}
+
void dist_squared_ray_to_aabb_v3_precalc(
struct NearestRayToAABB_Precalc *data,
const float ray_origin[3], const float ray_direction[3])
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 8cb9ef837b2..e40692f4a88 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -53,6 +53,7 @@ set(SRC
intern/versioning_250.c
intern/versioning_260.c
intern/versioning_270.c
+ intern/versioning_280.c
intern/versioning_defaults.c
intern/versioning_legacy.c
intern/writefile.c
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9ee109431e7..9af85cc9ee9 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -72,6 +72,7 @@
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_layer_types.h"
#include "DNA_lamp_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
@@ -102,6 +103,8 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
+#include "RNA_access.h"
+
#include "MEM_guardedalloc.h"
#include "BLI_endian_switch.h"
@@ -3967,6 +3970,7 @@ static void lib_link_material(FileData *fd, Main *main)
static void direct_link_material(FileData *fd, Material *ma)
{
int a;
+ MaterialEngineSettings *mes;
ma->adt = newdataadr(fd, ma->adt);
direct_link_animdata(fd, ma->adt);
@@ -3987,6 +3991,11 @@ static void direct_link_material(FileData *fd, Material *ma)
ma->preview = direct_link_preview_image(fd, ma->preview);
BLI_listbase_clear(&ma->gpumaterial);
+
+ link_list(fd, &ma->engines_settings);
+ for (mes = ma->engines_settings.first; mes; mes = mes->next) {
+ mes->data = newdataadr(fd, mes->data);
+ }
}
/* ************ READ PARTICLE SETTINGS ***************** */
@@ -4709,12 +4718,12 @@ static void direct_link_latt(FileData *fd, Lattice *lt)
/* ************ READ OBJECT ***************** */
static void lib_link_modifiers__linkModifiers(
- void *userData, Object *ob, ID **idpoin, int cd_flag)
+ void *userData, Object *ob, ID **idpoin, int cb_flag)
{
FileData *fd = userData;
*idpoin = newlibadr(fd, ob->id.lib, *idpoin);
- if (*idpoin != NULL && (cd_flag & IDWALK_USER) != 0) {
+ if (*idpoin != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
id_us_plus_no_lib(*idpoin);
}
}
@@ -5549,6 +5558,7 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->bb = NULL;
ob->derivedDeform = NULL;
ob->derivedFinal = NULL;
+ ob->collection_settings = NULL;
BLI_listbase_clear(&ob->gpulamp);
link_list(fd, &ob->pc_ids);
@@ -5630,11 +5640,29 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
}
#endif
+static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ link->data = newlibadr_us(fd, lib, link->data);
+ BLI_assert(link->data);
+ }
+
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ link->data = newlibadr_us(fd, lib, link->data);
+ BLI_assert(link->data);
+ }
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ lib_link_scene_collection(fd, lib, nsc);
+ }
+}
+
static void lib_link_scene(FileData *fd, Main *main)
{
Scene *sce;
- Base *base, *next;
+ BaseLegacy *base_legacy, *base_legacy_next;
Sequence *seq;
+ SceneLayer *sl;
SceneRenderLayer *srl;
FreestyleModuleConfig *fmc;
FreestyleLineSet *fls;
@@ -5684,17 +5712,17 @@ static void lib_link_scene(FileData *fd, Main *main)
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;
+ for (base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) {
+ base_legacy_next = base_legacy->next;
- base->object = newlibadr_us(fd, sce->id.lib, base->object);
+ base_legacy->object = newlibadr_us(fd, sce->id.lib, base_legacy->object);
- if (base->object == NULL) {
+ if (base_legacy->object == NULL) {
blo_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB: object lost from scene: '%s'"),
sce->id.name + 2);
- BLI_remlink(&sce->base, base);
- if (base == sce->basact) sce->basact = NULL;
- MEM_freeN(base);
+ BLI_remlink(&sce->base, base_legacy);
+ if (base_legacy == sce->basact) sce->basact = NULL;
+ MEM_freeN(base_legacy);
}
}
@@ -5780,6 +5808,15 @@ static void lib_link_scene(FileData *fd, Main *main)
/* Motion Tracking */
sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip);
+ lib_link_scene_collection(fd, sce->id.lib, sce->collection);
+
+ for (sl = sce->render_layers.first; sl; sl = sl->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ /* we only bump the use count for the collection objects */
+ base->object = newlibadr(fd, sce->id.lib, base->object);
+ }
+ }
+
#ifdef USE_SETSCENE_CHECK
if (sce->set != NULL) {
/* link flag for scenes with set would be reset later,
@@ -5883,13 +5920,54 @@ static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *vi
direct_link_curvemapping(fd, view_settings->curve_mapping);
}
+static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
+{
+ link_list(fd, &sc->objects);
+ link_list(fd, &sc->filter_objects);
+ link_list(fd, &sc->scene_collections);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ direct_link_scene_collection(fd, nsc);
+ }
+}
+
+static void direct_link_engine_settings(FileData *fd, ListBase *lb)
+{
+ link_list(fd, lb);
+ for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
+ link_list(fd, &ces->properties);
+ }
+}
+
+static void direct_link_layer_collections(FileData *fd, ListBase *lb)
+{
+ link_list(fd, lb);
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ lc->scene_collection = newdataadr(fd, lc->scene_collection);
+
+ link_list(fd, &lc->object_bases);
+
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ link->data = newdataadr(fd, link->data);
+ }
+
+ link_list(fd, &lc->overrides);
+
+ direct_link_engine_settings(fd, &lc->engine_settings);
+
+ direct_link_layer_collections(fd, &lc->layer_collections);
+ }
+}
+
static void direct_link_scene(FileData *fd, Scene *sce)
{
Editing *ed;
Sequence *seq;
MetaStack *ms;
RigidBodyWorld *rbw;
+ SceneLayer *sl;
SceneRenderLayer *srl;
+ RenderEngineSettings *res;
sce->theDag = NULL;
sce->depsgraph = NULL;
@@ -6139,6 +6217,24 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->preview = direct_link_preview_image(fd, sce->preview);
direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve);
+
+ /* this runs before the very first doversion */
+ if (sce->collection) {
+ sce->collection = newdataadr(fd, sce->collection);
+ direct_link_scene_collection(fd, sce->collection);
+ }
+
+ link_list(fd, &sce->render_layers);
+ for (sl = sce->render_layers.first; sl; sl = sl->next) {
+ link_list(fd, &sl->object_bases);
+ sl->basact = newdataadr(fd, sl->basact);
+ direct_link_layer_collections(fd, &sl->layer_collections);
+ }
+
+ link_list(fd, &sce->engines_settings);
+ for (res = sce->engines_settings.first; res; res = res->next) {
+ res->data = newdataadr(fd, res->data);
+ }
}
/* ************ READ WM ***************** */
@@ -6482,6 +6578,10 @@ static void lib_link_screen(FileData *fd, Main *main)
slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd);
}
+ else if (sl->spacetype == SPACE_COLLECTIONS) {
+ SpaceCollections *slayer = (SpaceCollections *)sl;
+ slayer->flag |= SC_COLLECTION_DATA_REFRESH;
+ }
}
}
sc->id.tag &= ~LIB_TAG_NEED_LINK;
@@ -6867,6 +6967,10 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
slogic->gpd = restore_pointer_by_name(id_map, (ID *)slogic->gpd, USER_REAL);
}
+ else if (sl->spacetype == SPACE_COLLECTIONS) {
+ SpaceCollections *slayer = (SpaceCollections *)sl;
+ slayer->flag |= SC_COLLECTION_DATA_REFRESH;
+ }
}
}
}
@@ -7261,6 +7365,10 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
sclip->scopes.track_preview = NULL;
sclip->scopes.ok = 0;
}
+ else if (sl->spacetype == SPACE_COLLECTIONS) {
+ SpaceCollections *slayer = (SpaceCollections *)sl;
+ slayer->flag |= SC_COLLECTION_DATA_REFRESH;
+ }
}
BLI_listbase_clear(&sa->actionzones);
@@ -7457,7 +7565,7 @@ static void lib_link_group(FileData *fd, Main *main)
if (add_us) {
id_us_ensure_real(&group->id);
}
- BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */
+ BKE_group_object_unlink(group, NULL); /* removes NULL entries */
}
}
}
@@ -8389,6 +8497,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
blo_do_versions_250(fd, lib, main);
blo_do_versions_260(fd, lib, main);
blo_do_versions_270(fd, lib, main);
+ blo_do_versions_280(fd, lib, main);
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
@@ -8400,8 +8509,8 @@ static void do_versions_after_linking(Main *main)
{
// printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name,
// main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile);
-
do_versions_after_linking_270(main);
+ do_versions_after_linking_280(main);
}
static void lib_link_all(FileData *fd, Main *main)
@@ -9308,7 +9417,7 @@ static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
}
static void expand_object_expandModifiers(
- void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag))
+ void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cb_flag))
{
struct { FileData *fd; Main *mainvar; } *data= userData;
@@ -9484,9 +9593,24 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
}
}
+static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ expand_doit(fd, mainvar, link->data);
+ }
+
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ expand_doit(fd, mainvar, link->data);
+ }
+
+ for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) {
+ expand_scene_collection(fd, mainvar, nsc);
+ }
+}
+
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
- Base *base;
+ BaseLegacy *base;
SceneRenderLayer *srl;
FreestyleModuleConfig *module;
FreestyleLineSet *lineset;
@@ -9553,6 +9677,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
expand_doit(fd, mainvar, sce->clip);
+
+ expand_scene_collection(fd, mainvar, sce->collection);
}
static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
@@ -9799,7 +9925,7 @@ static bool object_in_any_scene(Main *mainvar, Object *ob)
static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Library *lib, const short flag)
{
Object *ob;
- Base *base;
+ BaseLegacy *base;
const unsigned int active_lay = (flag & FILE_ACTIVELAY) ? BKE_screen_view3d_layer_active(v3d, scene) : 0;
const bool is_link = (flag & FILE_LINK) != 0;
@@ -9820,7 +9946,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
}
if (do_it) {
- base = MEM_callocN(sizeof(Base), __func__);
+ base = MEM_callocN(sizeof(BaseLegacy), __func__);
BLI_addtail(&scene->base, base);
if (active_lay) {
@@ -9835,7 +9961,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
base->object = ob;
base->lay = ob->lay;
- base->flag = ob->flag;
+ BKE_scene_base_flag_sync_from_object(base);
CLAMP_MIN(ob->id.us, 0);
id_us_plus_no_lib((ID *)ob);
@@ -9851,7 +9977,7 @@ static void give_base_to_groups(
Main *mainvar, Scene *scene, View3D *v3d, Library *UNUSED(lib), const short UNUSED(flag))
{
Group *group;
- Base *base;
+ BaseLegacy *base;
Object *ob;
const unsigned int active_lay = BKE_screen_view3d_layer_active(v3d, scene);
@@ -9868,8 +9994,8 @@ static void give_base_to_groups(
/* assign the base */
base = BKE_scene_base_add(scene, ob);
- base->flag |= SELECT;
- base->object->flag = base->flag;
+ base->flag_legacy |= SELECT;
+ BKE_scene_base_flag_sync_from_base(base);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
scene->basact = base;
@@ -9951,10 +10077,10 @@ static ID *link_named_part(
static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const short flag)
{
if (scene) {
- Base *base;
+ BaseLegacy *base;
Object *ob;
- base = MEM_callocN(sizeof(Base), "app_nam_part");
+ base = MEM_callocN(sizeof(BaseLegacy), "app_nam_part");
BLI_addtail(&scene->base, base);
ob = (Object *)id;
@@ -9967,12 +10093,12 @@ static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const sho
ob->mode = OB_MODE_OBJECT;
base->lay = ob->lay;
base->object = ob;
- base->flag = ob->flag;
+ base->flag_legacy = ob->flag;
id_us_plus_no_lib((ID *)ob);
if (flag & FILE_AUTOSELECT) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
+ base->flag_legacy |= SELECT;
+ BKE_scene_base_flag_sync_from_base(base);
/* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
}
}
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index d97bef13a78..50cdeca16b5 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -34,6 +34,8 @@
#define __READFILE_H__
#include "zlib.h"
+#include "DNA_sdna_types.h"
+#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h" /* for ReportType */
struct OldNewMap;
@@ -169,8 +171,10 @@ void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Mai
void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *main);
+void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *main);
void do_versions_after_linking_270(struct Main *main);
+void do_versions_after_linking_280(struct Main *main);
#endif
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 1956a17d57b..943e5479d9a 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -736,7 +736,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 250) {
bScreen *screen;
Scene *scene;
- Base *base;
+ BaseLegacy *base;
Material *ma;
Camera *cam;
Mesh *me;
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 21880fdb2dd..5df20d443a6 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -216,6 +216,10 @@ static void anim_change_prop_name(FCurve *fcu,
static void do_version_hue_sat_node(bNodeTree *ntree, bNode *node)
{
+ if (node->storage == NULL) {
+ return;
+ }
+
/* Make sure new sockets are properly created. */
node_verify_socket_templates(ntree, node);
/* Convert value from old storage to new sockets. */
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
new file mode 100644
index 00000000000..432d8be0a6d
--- /dev/null
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -0,0 +1,187 @@
+/*
+ * ***** 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): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/blenloader/intern/versioning_280.c
+ * \ingroup blenloader
+ */
+
+/* allow readfile to use deprecated functionality */
+#define DNA_DEPRECATED_ALLOW
+
+#include "DNA_object_types.h"
+#include "DNA_layer_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_genfile.h"
+
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BLO_readfile.h"
+#include "readfile.h"
+
+#include "MEM_guardedalloc.h"
+
+void do_versions_after_linking_280(Main *main)
+{
+ if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ /* since we don't have access to FileData we check the (always valid) first render layer instead */
+ if (scene->render_layers.first == NULL) {
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name));
+
+ SceneCollection *collections[20] = {NULL};
+ bool is_visible[20];
+
+ int lay_used = 0;
+ for (int i = 0; i < 20; i++) {
+ char name[MAX_NAME];
+
+ BLI_snprintf(name, sizeof(collections[i]->name), "%d", i + 1);
+ collections[i] = BKE_collection_add(scene, sc_master, name);
+
+ is_visible[i] = (scene->lay & (1 << i));
+ }
+
+ for (Base *base = scene->base.first; base; base = base->next) {
+ lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */
+
+ for (int i = 0; i < 20; i++) {
+ if ((base->lay & (1 << i)) != 0) {
+ BKE_collection_object_add(scene, collections[i], base->object);
+ }
+ }
+ }
+
+ scene->active_layer = 0;
+
+ if (!BKE_scene_uses_blender_game(scene)) {
+ for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
+
+ SceneLayer *sl = BKE_scene_layer_add(scene, srl->name);
+ BKE_scene_layer_engine_set(sl, scene->r.engine);
+
+ if (srl->mat_override) {
+ BKE_collection_override_datablock_add((LayerCollection *)sl->layer_collections.first, "material", (ID *)srl->mat_override);
+ }
+
+ if (srl->light_override && BKE_scene_uses_blender_internal(scene)) {
+ /* not sure how we handle this, pending until we design the override system */
+ TODO_LAYER_OVERRIDE;
+ }
+
+ if (srl->lay != scene->lay) {
+ /* unlink master collection */
+ BKE_collection_unlink(sl, sl->layer_collections.first);
+
+ /* add new collection bases */
+ for (int i = 0; i < 20; i++) {
+ if ((srl->lay & (1 << i)) != 0) {
+ BKE_collection_link(sl, collections[i]);
+ }
+ }
+ }
+
+ /* for convenience set the same active object in all the layers */
+ if (scene->basact) {
+ sl->basact = BKE_scene_layer_base_find(sl, scene->basact->object);
+ }
+
+ /* TODO: passes, samples, mask_layesr, exclude, ... */
+ }
+
+ if (BLI_findlink(&scene->render_layers, scene->r.actlay)) {
+ scene->active_layer = scene->r.actlay;
+ }
+ }
+
+ SceneLayer *sl = BKE_scene_layer_add(scene, "Render Layer");
+
+ /* In this particular case we can safely assume the data struct */
+ LayerCollection *lc = ((LayerCollection *)sl->layer_collections.first)->layer_collections.first;
+ for (int i = 0; i < 20; i++) {
+ if (!is_visible[i]) {
+ lc->flag &= ~COLLECTION_VISIBLE;
+ }
+ lc = lc->next;
+ }
+
+ /* but we still need to make the flags synced */
+ BKE_scene_layer_base_flag_recalculate(sl);
+
+ /* convert active base */
+ if (scene->basact) {
+ sl->basact = BKE_scene_layer_base_find(sl, scene->basact->object);
+ }
+
+ /* convert selected bases */
+ for (Base *base = scene->base.first; base; base = base->next) {
+ Base *ob_base = BKE_scene_layer_base_find(sl, base->object);
+ if ((base->flag & SELECT) != 0) {
+ if ((ob_base->flag & BASE_SELECTABLED) != 0) {
+ ob_base->flag |= BASE_SELECTED;
+ }
+ }
+ else {
+ ob_base->flag &= ~BASE_SELECTED;
+ }
+ }
+
+ /* TODO: copy scene render data to layer */
+
+ /* Cleanup */
+ for (int i = 0; i < 20; i++) {
+ if ((lay_used & (1 << i)) == 0) {
+ BKE_collection_remove(scene, collections[i]);
+ }
+ }
+
+ /* remove bases once and for all */
+ for (Base *base = scene->base.first; base; base = base->next) {
+ id_us_min(&base->object->id);
+ }
+ BLI_freelistN(&scene->base);
+ scene->basact = NULL;
+ }
+ }
+ }
+}
+
+void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
+{
+ if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "render_layers")) {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ /* Master Collection */
+ scene->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
+ BLI_strncpy(scene->collection->name, "Master Collection", sizeof(scene->collection->name));
+ }
+ }
+ }
+}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 5011f9836b7..16d73557bb0 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -120,6 +120,7 @@
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_lamp_types.h"
+#include "DNA_layer_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
@@ -799,22 +800,18 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
static void write_actions(WriteData *wd, ListBase *idbase)
{
- bAction *act;
- bActionGroup *grp;
- TimeMarker *marker;
-
- for (act = idbase->first; act; act = act->id.next) {
+ for (bAction *act = idbase->first; act; act = act->id.next) {
if (act->id.us > 0 || wd->current) {
writestruct(wd, ID_AC, bAction, 1, act);
write_iddata(wd, &act->id);
write_fcurves(wd, &act->curves);
- for (grp = act->groups.first; grp; grp = grp->next) {
+ for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) {
writestruct(wd, DATA, bActionGroup, 1, grp);
}
- for (marker = act->markers.first; marker; marker = marker->next) {
+ for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
writestruct(wd, DATA, TimeMarker, 1, marker);
}
}
@@ -1280,13 +1277,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
}
static void write_particlesettings(WriteData *wd, ListBase *idbase)
{
- ParticleSettings *part;
- ParticleDupliWeight *dw;
- GroupObject *go;
- int a;
-
- part = idbase->first;
- while (part) {
+ for (ParticleSettings *part = idbase->first; part; part = part->id.next) {
if (part->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_PA, ParticleSettings, 1, part);
@@ -1306,24 +1297,23 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
write_curvemapping(wd, part->roughcurve);
}
- dw = part->dupliweights.first;
- for (; dw; dw = dw->next) {
+ for (ParticleDupliWeight *dw = part->dupliweights.first; 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++);
+ for (GroupObject *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) {
+ for (BoidState *state = part->boids->states.first; state; state = state->next) {
write_boid_state(wd, state);
}
}
@@ -1331,13 +1321,12 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
}
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int 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)
@@ -1834,10 +1823,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
static void write_objects(WriteData *wd, ListBase *idbase)
{
- Object *ob;
-
- ob = idbase->first;
- while (ob) {
+ for (Object *ob = idbase->first; ob; ob = ob->id.next) {
if (ob->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_OB, Object, 1, ob);
@@ -1893,11 +1879,9 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writelist(wd, DATA, LinkData, &ob->pc_ids);
writelist(wd, DATA, LodLevel, &ob->lodlevels);
- }
- write_previews(wd, ob->preview);
-
- ob = ob->id.next;
+ write_previews(wd, ob->preview);
+ }
}
mywrite_flush(wd);
@@ -1906,26 +1890,19 @@ static void write_objects(WriteData *wd, ListBase *idbase)
static void write_vfonts(WriteData *wd, ListBase *idbase)
{
- VFont *vf;
- PackedFile *pf;
-
- vf = idbase->first;
- while (vf) {
+ for (VFont *vf = idbase->first; vf; vf = vf->id.next) {
if (vf->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_VF, VFont, 1, vf);
write_iddata(wd, &vf->id);
/* direct data */
-
if (vf->packedfile) {
- pf = vf->packedfile;
+ PackedFile *pf = vf->packedfile;
writestruct(wd, DATA, PackedFile, 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
}
-
- vf = vf->id.next;
}
mywrite_flush(wd);
@@ -1934,11 +1911,7 @@ static void write_vfonts(WriteData *wd, ListBase *idbase)
static void write_keys(WriteData *wd, ListBase *idbase)
{
- Key *key;
- KeyBlock *kb;
-
- key = idbase->first;
- while (key) {
+ for (Key *key = idbase->first; key; key = key->id.next) {
if (key->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_KE, Key, 1, key);
@@ -1949,17 +1922,13 @@ static void write_keys(WriteData *wd, ListBase *idbase)
}
/* direct data */
- kb = key->block.first;
- while (kb) {
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
writestruct(wd, DATA, KeyBlock, 1, kb);
if (kb->data) {
writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
}
- kb = kb->next;
}
}
-
- key = key->id.next;
}
mywrite_flush(wd);
@@ -1967,10 +1936,7 @@ static void write_keys(WriteData *wd, ListBase *idbase)
static void write_cameras(WriteData *wd, ListBase *idbase)
{
- Camera *cam;
-
- cam = idbase->first;
- while (cam) {
+ for (Camera *cam = idbase->first; cam; cam = cam->id.next) {
if (cam->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_CA, Camera, 1, cam);
@@ -1980,18 +1946,12 @@ static void write_cameras(WriteData *wd, ListBase *idbase)
write_animdata(wd, cam->adt);
}
}
-
- cam = cam->id.next;
}
}
static void write_mballs(WriteData *wd, ListBase *idbase)
{
- MetaBall *mb;
- MetaElem *ml;
-
- mb = idbase->first;
- while (mb) {
+ for (MetaBall *mb = idbase->first; mb; mb = mb->id.next) {
if (mb->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_MB, MetaBall, 1, mb);
@@ -2003,23 +1963,16 @@ static void write_mballs(WriteData *wd, ListBase *idbase)
write_animdata(wd, mb->adt);
}
- ml = mb->elems.first;
- while (ml) {
+ for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) {
writestruct(wd, DATA, MetaElem, 1, ml);
- ml = ml->next;
}
}
- mb = mb->id.next;
}
}
static void write_curves(WriteData *wd, ListBase *idbase)
{
- Curve *cu;
- Nurb *nu;
-
- cu = idbase->first;
- while (cu) {
+ for (Curve *cu = idbase->first; cu; cu = cu->id.next) {
if (cu->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_CU, Curve, 1, cu);
@@ -2038,13 +1991,10 @@ static void write_curves(WriteData *wd, ListBase *idbase)
}
else {
/* is also the order of reading */
- nu = cu->nurb.first;
- while (nu) {
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
writestruct(wd, DATA, Nurb, 1, nu);
- nu = nu->next;
}
- nu = cu->nurb.first;
- while (nu) {
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
}
@@ -2057,11 +2007,9 @@ static void write_curves(WriteData *wd, ListBase *idbase)
writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
}
}
- nu = nu->next;
}
}
}
- cu = cu->id.next;
}
mywrite_flush(wd);
@@ -2183,15 +2131,13 @@ static void write_customdata(
static void write_meshes(WriteData *wd, ListBase *idbase)
{
- Mesh *mesh;
- bool save_for_old_blender = false;
-
#ifdef USE_BMESH_SAVE_AS_COMPAT
- save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */
+ const bool save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */
+#else
+ const bool save_for_old_blender = false;
#endif
- mesh = idbase->first;
- while (mesh) {
+ for (Mesh *mesh = idbase->first; mesh; mesh = mesh->id.next) {
CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
@@ -2336,8 +2282,6 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
if (players && players != players_buff) {
MEM_freeN(players);
}
-
- mesh = mesh->id.next;
}
mywrite_flush(wd);
@@ -2345,10 +2289,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
static void write_lattices(WriteData *wd, ListBase *idbase)
{
- Lattice *lt;
-
- lt = idbase->first;
- while (lt) {
+ for (Lattice *lt = idbase->first; lt; lt = lt->id.next) {
if (lt->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_LT, Lattice, 1, lt);
@@ -2363,9 +2304,7 @@ static void write_lattices(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
-
}
- lt = lt->id.next;
}
mywrite_flush(wd);
@@ -2373,14 +2312,10 @@ static void write_lattices(WriteData *wd, ListBase *idbase)
static void write_images(WriteData *wd, ListBase *idbase)
{
- Image *ima;
- PackedFile *pf;
- ImageView *iv;
- ImagePackedFile *imapf;
-
- ima = idbase->first;
- while (ima) {
+ for (Image *ima = idbase->first; ima; ima = ima->id.next) {
if (ima->id.us > 0 || wd->current) {
+ ImagePackedFile *imapf;
+
/* Some trickery to keep forward compatibility of packed images. */
BLI_assert(ima->packedfile == NULL);
if (ima->packedfiles.first != NULL) {
@@ -2395,7 +2330,7 @@ static void write_images(WriteData *wd, ListBase *idbase)
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
writestruct(wd, DATA, ImagePackedFile, 1, imapf);
if (imapf->packedfile) {
- pf = imapf->packedfile;
+ PackedFile *pf = imapf->packedfile;
writestruct(wd, DATA, PackedFile, 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
@@ -2403,14 +2338,13 @@ static void write_images(WriteData *wd, ListBase *idbase)
write_previews(wd, ima->preview);
- for (iv = ima->views.first; iv; iv = iv->next) {
+ for (ImageView *iv = ima->views.first; iv; iv = iv->next) {
writestruct(wd, DATA, ImageView, 1, iv);
}
writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
ima->packedfile = NULL;
}
- ima = ima->id.next;
}
mywrite_flush(wd);
@@ -2418,10 +2352,7 @@ static void write_images(WriteData *wd, ListBase *idbase)
static void write_textures(WriteData *wd, ListBase *idbase)
{
- Tex *tex;
-
- tex = idbase->first;
- while (tex) {
+ for (Tex *tex = idbase->first; tex; tex = tex->id.next) {
if (tex->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_TE, Tex, 1, tex);
@@ -2462,19 +2393,29 @@ static void write_textures(WriteData *wd, ListBase *idbase)
write_previews(wd, tex->preview);
}
- tex = tex->id.next;
}
mywrite_flush(wd);
}
-static void write_materials(WriteData *wd, ListBase *idbase)
+static void write_material_engines_settings(WriteData *wd, ListBase *lb)
{
- Material *ma;
- int a;
+ for (MaterialEngineSettings *res = lb->first; res; res = res->next) {
+ writestruct(wd, DATA, MaterialEngineSettings, 1, res);
+
+ if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
+ writestruct(wd, DATA, MaterialEngineSettingsClay, 1, res->data);
+ }
+ else {
+ /* No engine matched */
+ /* error: don't know how to write this file */
+ }
+ }
+}
- ma = idbase->first;
- while (ma) {
+static void write_materials(WriteData *wd, ListBase *idbase)
+{
+ for (Material *ma = idbase->first; ma; ma = ma->id.next) {
if (ma->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_MA, Material, 1, ma);
@@ -2484,7 +2425,7 @@ static void write_materials(WriteData *wd, ListBase *idbase)
write_animdata(wd, ma->adt);
}
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (ma->mtex[a]) {
writestruct(wd, DATA, MTex, 1, ma->mtex[a]);
}
@@ -2504,18 +2445,15 @@ static void write_materials(WriteData *wd, ListBase *idbase)
}
write_previews(wd, ma->preview);
+
+ write_material_engines_settings(wd, &ma->engines_settings);
}
- ma = ma->id.next;
}
}
static void write_worlds(WriteData *wd, ListBase *idbase)
{
- World *wrld;
- int a;
-
- wrld = idbase->first;
- while (wrld) {
+ for (World *wrld = idbase->first; wrld; wrld = wrld->id.next) {
if (wrld->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_WO, World, 1, wrld);
@@ -2525,7 +2463,7 @@ static void write_worlds(WriteData *wd, ListBase *idbase)
write_animdata(wd, wrld->adt);
}
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (wrld->mtex[a]) {
writestruct(wd, DATA, MTex, 1, wrld->mtex[a]);
}
@@ -2539,17 +2477,12 @@ static void write_worlds(WriteData *wd, ListBase *idbase)
write_previews(wd, wrld->preview);
}
- wrld = wrld->id.next;
}
}
static void write_lamps(WriteData *wd, ListBase *idbase)
{
- Lamp *la;
- int a;
-
- la = idbase->first;
- while (la) {
+ for (Lamp *la = idbase->first; la; la = la->id.next) {
if (la->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_LA, Lamp, 1, la);
@@ -2560,7 +2493,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
}
/* direct data */
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (la->mtex[a]) {
writestruct(wd, DATA, MTex, 1, la->mtex[a]);
}
@@ -2577,9 +2510,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
}
write_previews(wd, la->preview);
-
}
- la = la->id.next;
}
mywrite_flush(wd);
@@ -2626,24 +2557,70 @@ static void write_paint(WriteData *wd, Paint *p)
}
}
+static void write_scene_collection(WriteData *wd, SceneCollection *sc)
+{
+ writestruct(wd, DATA, SceneCollection, 1, sc);
+
+ writelist(wd, DATA, LinkData, &sc->objects);
+ writelist(wd, DATA, LinkData, &sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ write_scene_collection(wd, nsc);
+ }
+}
+
+static void write_collection_engine_settings(WriteData *wd, ListBase *lb)
+{
+ for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
+ writestruct(wd, DATA, CollectionEngineSettings, 1, ces);
+
+ for (CollectionEngineProperty *prop = ces->properties.first; prop; prop = prop->next) {
+ switch (prop->type) {
+ case COLLECTION_PROP_TYPE_FLOAT:
+ writestruct(wd, DATA, CollectionEnginePropertyFloat, 1, prop);
+ break;
+ case COLLECTION_PROP_TYPE_INT:
+ writestruct(wd, DATA, CollectionEnginePropertyInt, 1, prop);
+ break;
+ default:
+ ; /* error: don't know how to write this file */
+ }
+ }
+ }
+}
+
+static void write_layer_collections(WriteData *wd, ListBase *lb)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ writestruct(wd, DATA, LayerCollection, 1, lc);
+
+ writelist(wd, DATA, LinkData, &lc->object_bases);
+ writelist(wd, DATA, CollectionOverride, &lc->overrides);
+
+ write_collection_engine_settings(wd, &lc->engine_settings);
+
+ write_layer_collections(wd, &lc->layer_collections);
+ }
+}
+
+static void write_render_engines_settings(WriteData *wd, ListBase *lb)
+{
+ for (RenderEngineSettings *res = lb->first; res; res = res->next) {
+ writestruct(wd, DATA, RenderEngineSettings, 1, res);
+
+ if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
+ writestruct(wd, DATA, RenderEngineSettingsClay, 1, res->data);
+ }
+ else {
+ /* No engine matched */
+ /* error: don't know how to write this file */
+ }
+ }
+}
+
static void write_scenes(WriteData *wd, ListBase *scebase)
{
- Scene *sce;
- Base *base;
- Editing *ed;
- Sequence *seq;
- MetaStack *ms;
- Strip *strip;
- TimeMarker *marker;
- TransformOrientation *ts;
- SceneRenderLayer *srl;
- SceneRenderView *srv;
- ToolSettings *tos;
- FreestyleModuleConfig *fmc;
- FreestyleLineSet *fls;
-
- sce = scebase->first;
- while (sce) {
+ for (Scene *sce = scebase->first; sce; sce = sce->id.next) {
/* write LibData */
writestruct(wd, ID_SCE, Scene, 1, sce);
write_iddata(wd, &sce->id);
@@ -2654,13 +2631,11 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_keyingsets(wd, &sce->keyingsets);
/* direct data */
- base = sce->base.first;
- while (base) {
- writestruct(wd, DATA, Base, 1, base);
- base = base->next;
+ for (BaseLegacy *base = sce->base.first; base; base = base->next) {
+ writestruct(wd, DATA, BaseLegacy, 1, base);
}
- tos = sce->toolsettings;
+ ToolSettings *tos = sce->toolsettings;
writestruct(wd, DATA, ToolSettings, 1, tos);
if (tos->vpaint) {
writestruct(wd, DATA, VPaint, 1, tos->vpaint);
@@ -2699,8 +2674,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_paint(wd, &tos->imapaint.paint);
- ed = sce->ed;
+ Editing *ed = sce->ed;
if (ed) {
+ Sequence *seq;
+
writestruct(wd, DATA, Editing, 1, ed);
/* reset write flags too */
@@ -2747,7 +2724,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
- strip = seq->strip;
+ Strip *strip = seq->strip;
writestruct(wd, DATA, Strip, 1, strip);
if (seq->flag & SEQ_USE_CROP && strip->crop) {
writestruct(wd, DATA, StripCrop, 1, strip->crop);
@@ -2779,7 +2756,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
SEQ_END
/* new; meta stack too, even when its nasty restore code */
- for (ms = ed->metastack.first; ms; ms = ms->next) {
+ for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) {
writestruct(wd, DATA, MetaStack, 1, ms);
}
}
@@ -2805,27 +2782,27 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
}
/* writing dynamic list of TimeMarkers to the blend file */
- for (marker = sce->markers.first; marker; marker = marker->next) {
+ for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) {
writestruct(wd, DATA, TimeMarker, 1, marker);
}
/* writing dynamic list of TransformOrientations to the blend file */
- for (ts = sce->transform_spaces.first; ts; ts = ts->next) {
+ for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
writestruct(wd, DATA, TransformOrientation, 1, ts);
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
writestruct(wd, DATA, SceneRenderLayer, 1, srl);
- for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
}
- for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
writestruct(wd, DATA, FreestyleLineSet, 1, fls);
}
}
/* writing MultiView to the blend file */
- for (srv = sce->r.views.first; srv; srv = srv->next) {
+ for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
writestruct(wd, DATA, SceneRenderView, 1, srv);
}
@@ -2845,8 +2822,16 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_previews(wd, sce->preview);
write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
+ write_scene_collection(wd, sce->collection);
+
+ for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+ writestruct(wd, DATA, SceneLayer, 1, sl);
+ writelist(wd, DATA, Base, &sl->object_bases);
+ write_layer_collections(wd, &sl->layer_collections);
+ }
+
+ write_render_engines_settings(wd, &sce->engines_settings);
- sce = sce->id.next;
}
mywrite_flush(wd);
@@ -2854,13 +2839,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
static void write_gpencils(WriteData *wd, ListBase *lb)
{
- bGPdata *gpd;
- bGPDlayer *gpl;
- bGPDframe *gpf;
- bGPDstroke *gps;
- bGPDpalette *palette;
-
- for (gpd = lb->first; gpd; gpd = gpd->id.next) {
+ for (bGPdata *gpd = lb->first; gpd; gpd = gpd->id.next) {
if (gpd->id.us > 0 || wd->current) {
/* write gpd data block to file */
writestruct(wd, ID_GD, bGPdata, 1, gpd);
@@ -2872,22 +2851,21 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
/* write grease-pencil layers to file */
writelist(wd, DATA, bGPDlayer, &gpd->layers);
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
-
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* write this layer's frames to file */
writelist(wd, DATA, bGPDframe, &gpl->frames);
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
-
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
/* write strokes */
writelist(wd, DATA, bGPDstroke, &gpf->strokes);
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
}
}
}
+
/* write grease-pencil palettes */
writelist(wd, DATA, bGPDpalette, &gpd->palettes);
- for (palette = gpd->palettes.first; palette; palette = palette->next) {
+ for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
writelist(wd, DATA, bGPDpalettecolor, &palette->colors);
}
}
@@ -2898,14 +2876,11 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
static void write_windowmanagers(WriteData *wd, ListBase *lb)
{
- wmWindowManager *wm;
- wmWindow *win;
-
- for (wm = lb->first; wm; wm = wm->id.next) {
+ for (wmWindowManager *wm = lb->first; wm; wm = wm->id.next) {
writestruct(wd, ID_WM, wmWindowManager, 1, wm);
write_iddata(wd, &wm->id);
- for (win = wm->windows.first; win; win = win->next) {
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
writestruct(wd, DATA, wmWindow, 1, win);
writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
}
@@ -2998,14 +2973,7 @@ static void write_soops(WriteData *wd, SpaceOops *so)
static void write_screens(WriteData *wd, ListBase *scrbase)
{
- bScreen *sc;
- ScrArea *sa;
- ScrVert *sv;
- ScrEdge *se;
-
- sc = scrbase->first;
- while (sc) {
-
+ for (bScreen *sc = scrbase->first; sc; sc = sc->id.next) {
/* write LibData */
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
writestruct(wd, ID_SCRN, bScreen, 1, sc);
@@ -3014,15 +2982,15 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
write_previews(wd, sc->preview);
/* direct data */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
writestruct(wd, DATA, ScrVert, 1, sv);
}
- for (se = sc->edgebase.first; se; se = se->next) {
+ for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
writestruct(wd, DATA, ScrEdge, 1, se);
}
- for (sa = sc->areabase.first; sa; sa = sa->next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
Panel *pa;
uiList *ui_list;
@@ -3052,8 +3020,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
}
}
- sl = sa->spacedata.first;
- while (sl) {
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
for (ar = sl->regionbase.first; ar; ar = ar->next) {
write_region(wd, ar, sl->spacetype);
}
@@ -3167,12 +3134,11 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
else if (sl->spacetype == SPACE_INFO) {
writestruct(wd, DATA, SpaceInfo, 1, sl);
}
-
- sl = sl->next;
+ else if (sl->spacetype == SPACE_COLLECTIONS) {
+ writestruct(wd, DATA, SpaceCollections, 1, sl);
+ }
}
}
-
- sc = sc->id.next;
}
mywrite_flush(wd);
@@ -3200,11 +3166,7 @@ static void write_bone(WriteData *wd, Bone *bone)
static void write_armatures(WriteData *wd, ListBase *idbase)
{
- bArmature *arm;
- Bone *bone;
-
- arm = idbase->first;
- while (arm) {
+ for (bArmature *arm = idbase->first; arm; arm = arm->id.next) {
if (arm->id.us > 0 || wd->current) {
writestruct(wd, ID_AR, bArmature, 1, arm);
write_iddata(wd, &arm->id);
@@ -3214,13 +3176,10 @@ static void write_armatures(WriteData *wd, ListBase *idbase)
}
/* Direct data */
- bone = arm->bonebase.first;
- while (bone) {
+ for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
write_bone(wd, bone);
- bone = bone->next;
}
}
- arm = arm->id.next;
}
mywrite_flush(wd);
@@ -3228,12 +3187,8 @@ static void write_armatures(WriteData *wd, ListBase *idbase)
static void write_texts(WriteData *wd, ListBase *idbase)
{
- Text *text;
- TextLine *tmp;
-
- text = idbase->first;
- while (text) {
- if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
+ for (Text *text = idbase->first; text; text = text->id.next) {
+ if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
text->flags &= ~TXT_ISEXT;
}
@@ -3247,21 +3202,14 @@ static void write_texts(WriteData *wd, ListBase *idbase)
if (!(text->flags & TXT_ISEXT)) {
/* now write the text data, in two steps for optimization in the readfunction */
- tmp = text->lines.first;
- while (tmp) {
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
writestruct(wd, DATA, TextLine, 1, tmp);
- tmp = tmp->next;
}
- tmp = text->lines.first;
- while (tmp) {
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
writedata(wd, DATA, tmp->len + 1, tmp->line);
- tmp = tmp->next;
}
}
-
-
- text = text->id.next;
}
mywrite_flush(wd);
@@ -3269,10 +3217,7 @@ static void write_texts(WriteData *wd, ListBase *idbase)
static void write_speakers(WriteData *wd, ListBase *idbase)
{
- Speaker *spk;
-
- spk = idbase->first;
- while (spk) {
+ for (Speaker *spk = idbase->first; spk; spk = spk->id.next) {
if (spk->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_SPK, Speaker, 1, spk);
@@ -3282,30 +3227,23 @@ static void write_speakers(WriteData *wd, ListBase *idbase)
write_animdata(wd, spk->adt);
}
}
- spk = spk->id.next;
}
}
static void write_sounds(WriteData *wd, ListBase *idbase)
{
- bSound *sound;
-
- PackedFile *pf;
-
- sound = idbase->first;
- while (sound) {
+ for (bSound *sound = idbase->first; sound; sound = sound->id.next) {
if (sound->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_SO, bSound, 1, sound);
write_iddata(wd, &sound->id);
if (sound->packedfile) {
- pf = sound->packedfile;
+ PackedFile *pf = sound->packedfile;
writestruct(wd, DATA, PackedFile, 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
}
- sound = sound->id.next;
}
mywrite_flush(wd);
@@ -3313,10 +3251,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase)
static void write_groups(WriteData *wd, ListBase *idbase)
{
- Group *group;
- GroupObject *go;
-
- for (group = idbase->first; group; group = group->id.next) {
+ for (Group *group = idbase->first; group; group = group->id.next) {
if (group->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_GR, Group, 1, group);
@@ -3324,10 +3259,8 @@ static void write_groups(WriteData *wd, ListBase *idbase)
write_previews(wd, group->preview);
- go = group->gobject.first;
- while (go) {
+ for (GroupObject *go = group->gobject.first; go; go = go->next) {
writestruct(wd, DATA, GroupObject, 1, go);
- go = go->next;
}
}
}
@@ -3337,9 +3270,7 @@ static void write_groups(WriteData *wd, ListBase *idbase)
static void write_nodetrees(WriteData *wd, ListBase *idbase)
{
- bNodeTree *ntree;
-
- for (ntree = idbase->first; ntree; ntree = ntree->id.next) {
+ for (bNodeTree *ntree = idbase->first; ntree; ntree = ntree->id.next) {
if (ntree->id.us > 0 || wd->current) {
writestruct(wd, ID_NT, bNodeTree, 1, ntree);
/* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
@@ -3423,9 +3354,7 @@ static void customnodes_free_deprecated_data(Main *mainvar)
static void write_brushes(WriteData *wd, ListBase *idbase)
{
- Brush *brush;
-
- for (brush = idbase->first; brush; brush = brush->id.next) {
+ for (Brush *brush = idbase->first; brush; brush = brush->id.next) {
if (brush->id.us > 0 || wd->current) {
writestruct(wd, ID_BR, Brush, 1, brush);
write_iddata(wd, &brush->id);
@@ -3442,9 +3371,7 @@ static void write_brushes(WriteData *wd, ListBase *idbase)
static void write_palettes(WriteData *wd, ListBase *idbase)
{
- Palette *palette;
-
- for (palette = idbase->first; palette; palette = palette->id.next) {
+ for (Palette *palette = idbase->first; palette; palette = palette->id.next) {
if (palette->id.us > 0 || wd->current) {
PaletteColor *color;
writestruct(wd, ID_PAL, Palette, 1, palette);
@@ -3459,9 +3386,7 @@ static void write_palettes(WriteData *wd, ListBase *idbase)
static void write_paintcurves(WriteData *wd, ListBase *idbase)
{
- PaintCurve *pc;
-
- for (pc = idbase->first; pc; pc = pc->id.next) {
+ for (PaintCurve *pc = idbase->first; pc; pc = pc->id.next) {
if (pc->id.us > 0 || wd->current) {
writestruct(wd, ID_PC, PaintCurve, 1, pc);
write_iddata(wd, &pc->id);
@@ -3511,10 +3436,7 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction
static void write_movieclips(WriteData *wd, ListBase *idbase)
{
- MovieClip *clip;
-
- clip = idbase->first;
- while (clip) {
+ for (MovieClip *clip = idbase->first; clip; clip = clip->id.next) {
if (clip->id.us > 0 || wd->current) {
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *object;
@@ -3541,8 +3463,6 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
object = object->next;
}
}
-
- clip = clip->id.next;
}
mywrite_flush(wd);
@@ -3550,10 +3470,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
static void write_masks(WriteData *wd, ListBase *idbase)
{
- Mask *mask;
-
- mask = idbase->first;
- while (mask) {
+ for (Mask *mask = idbase->first; mask; mask = mask->id.next) {
if (mask->id.us > 0 || wd->current) {
MaskLayer *masklay;
@@ -3601,8 +3518,6 @@ static void write_masks(WriteData *wd, ListBase *idbase)
}
}
}
-
- mask = mask->id.next;
}
mywrite_flush(wd);
@@ -3864,10 +3779,7 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
static void write_linestyles(WriteData *wd, ListBase *idbase)
{
- FreestyleLineStyle *linestyle;
- int a;
-
- for (linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
+ for (FreestyleLineStyle *linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
if (linestyle->id.us > 0 || wd->current) {
writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
write_iddata(wd, &linestyle->id);
@@ -3880,7 +3792,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (linestyle->mtex[a]) {
writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
}
@@ -3895,9 +3807,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
static void write_cachefiles(WriteData *wd, ListBase *idbase)
{
- CacheFile *cache_file;
-
- for (cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) {
+ for (CacheFile *cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) {
if (cache_file->id.us > 0 || wd->current) {
writestruct(wd, ID_CF, CacheFile, 1, cache_file);
@@ -3917,7 +3827,6 @@ static void write_libraries(WriteData *wd, Main *main)
bool found_one;
for (; main; main = main->next) {
-
a = tot = set_listbasepointers(main, lbarray);
/* test: is lib being used */
@@ -3926,16 +3835,13 @@ static void write_libraries(WriteData *wd, Main *main)
}
else {
found_one = false;
- while (tot--) {
+ while (!found_one && tot--) {
for (id = lbarray[tot]->first; id; id = id->next) {
if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
found_one = true;
break;
}
}
- if (found_one) {
- break;
- }
}
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index bb61f66e267..59ce91a3e70 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -945,6 +945,10 @@ void BM_mesh_bm_to_me(
/* propagate edited basis offsets to other shapes */
if (apply_offset) {
add_v3_v3(fp, *ofs_pt++);
+ /* Apply back new coordinates of offsetted shapekeys into BMesh.
+ * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous
+ * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */
+ copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp);
}
fp += 3;
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 4f5cf83f5ca..9c26ba83b44 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -69,17 +69,21 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
// write bone nodes
bArmature * armature = (bArmature *)ob_arm->data;
- ED_armature_to_edit(armature);
+ bool is_edited = armature->edbo != NULL;
- bArmature *arm = (bArmature *)ob_arm->data;
- for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
+ if (!is_edited)
+ ED_armature_to_edit(armature);
+
+ for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) {
// start from root bones
if (!bone->parent)
add_bone_node(bone, ob_arm, sce, se, child_objects);
}
- ED_armature_from_edit(armature);
- ED_armature_edit_free(armature);
+ if (!is_edited) {
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
+ }
}
void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 226f319cefd..5118234a587 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -57,6 +57,7 @@ extern "C" {
#include "BLI_fileops.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_main.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
@@ -264,7 +265,7 @@ void DocumentImporter::finish()
for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
Object *ob = *it;
- Base *base = BKE_scene_base_find(sce, ob);
+ BaseLegacy *base = (BaseLegacy *)BKE_scene_base_find(sce, ob);
if (base) {
BLI_remlink(&sce->base, base);
BKE_libblock_free_us(G.main, base->object);
@@ -418,7 +419,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
Object *obn = BKE_object_copy(G.main, source_ob);
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_scene_base_add(sce, obn);
+ BKE_collection_object_add_from(sce, source_ob, obn);
if (instance_node) {
anim_importer.read_node_transform(instance_node, obn);
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 76b51148509..7d9599c8554 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -66,7 +66,7 @@ EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettin
bool EffectsExporter::hasEffects(Scene *sce)
{
- Base *base = (Base *)sce->base.first;
+ BaseLegacy *base = (BaseLegacy *)sce->base.first;
while (base) {
Object *ob = base->object;
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
index b8971fffe3e..36bc176b1a6 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
@@ -43,8 +43,6 @@ void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const
NodeInput *valueSocket = this->getInputSocket(3);
NodeInput *facSocket = this->getInputSocket(4);
NodeOutput *outputSocket = this->getOutputSocket(0);
- bNode *editorsnode = getbNode();
- NodeHueSat *storage = (NodeHueSat *)editorsnode->storage;
ConvertRGBToHSVOperation *rgbToHSV = new ConvertRGBToHSVOperation();
converter.addOperation(rgbToHSV);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 4b73dfa1ec3..0f0d16907f4 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -121,11 +121,11 @@ struct BuilderWalkUserData {
static void modifier_walk(void *user_data,
struct Object * /*ob*/,
struct Object **obpoin,
- int /*cd_flag*/)
+ int /*cb_flag*/)
{
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
if (*obpoin) {
- data->builder->build_object(data->scene, NULL, *obpoin);
+ data->builder->build_object(data->scene, *obpoin);
}
}
@@ -138,7 +138,7 @@ void constraint_walk(bConstraint * /*con*/,
if (*idpoin) {
ID *id = *idpoin;
if (GS(id->name) == ID_OB) {
- data->builder->build_object(data->scene, NULL, (Object *)id);
+ data->builder->build_object(data->scene, (Object *)id);
}
}
}
@@ -337,9 +337,7 @@ void DepsgraphNodeBuilder::begin_build(Main *bmain) {
} FOREACH_NODETREE_END
}
-void DepsgraphNodeBuilder::build_group(Scene *scene,
- Base *base,
- Group *group)
+void DepsgraphNodeBuilder::build_group(Scene *scene, Group *group)
{
ID *group_id = &group->id;
if (group_id->tag & LIB_TAG_DOIT) {
@@ -348,7 +346,7 @@ void DepsgraphNodeBuilder::build_group(Scene *scene,
group_id->tag |= LIB_TAG_DOIT;
LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
- build_object(scene, base, go->ob);
+ build_object(scene, go->ob);
}
}
@@ -387,7 +385,7 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
return subgraph_node;
}
-void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
+void DepsgraphNodeBuilder::build_object(Scene *scene, Object *ob)
{
const bool has_object = (ob->id.tag & LIB_TAG_DOIT);
IDDepsNode *id_node = (has_object)
@@ -397,9 +395,12 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
* Do it for both new and existing ID nodes. This is so because several
* bases might be sharing same object.
*/
- if (base != NULL) {
- id_node->layers |= base->lay;
- }
+
+ /* Blender 2.8 transition: we don't have bases and do not have
+ * layer masks, but still want objects to be updated
+ */
+ id_node->layers |= ((1 << 20) - 1);
+
if (ob == scene->camera) {
/* Camera should always be updated, it used directly by viewport. */
id_node->layers |= (unsigned int)(-1);
@@ -415,7 +416,7 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
build_object_transform(scene, ob);
if (ob->parent != NULL) {
- build_object(scene, NULL, ob->parent);
+ build_object(scene, ob->parent);
}
if (ob->modifiers.first != NULL) {
BuilderWalkUserData data;
@@ -927,13 +928,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
*/
Curve *cu = (Curve *)obdata;
if (cu->bevobj != NULL) {
- build_object(scene, NULL, cu->bevobj);
+ build_object(scene, cu->bevobj);
}
if (cu->taperobj != NULL) {
- build_object(scene, NULL, cu->taperobj);
+ build_object(scene, cu->taperobj);
}
if (ob->type == OB_FONT && cu->textoncurve != NULL) {
- build_object(scene, NULL, cu->textoncurve);
+ build_object(scene, cu->textoncurve);
}
break;
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index c5035f35f6e..2f3f733b8db 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -32,7 +32,6 @@
#include "intern/depsgraph_types.h"
-struct Base;
struct CacheFile;
struct bGPdata;
struct ListBase;
@@ -126,8 +125,8 @@ struct DepsgraphNodeBuilder {
void build_scene(Main *bmain, Scene *scene);
SubgraphDepsNode *build_subgraph(Group *group);
- void build_group(Scene *scene, Base *base, Group *group);
- void build_object(Scene *scene, Base *base, Object *ob);
+ void build_group(Scene *scene, Group *group);
+ void build_object(Scene *scene, Object *ob);
void build_object_transform(Scene *scene, Object *ob);
void build_object_constraints(Scene *scene, Object *ob);
void build_pose_constraints(Object *ob, bPoseChannel *pchan);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
index 99e61692231..c7e8edb122e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -46,6 +46,7 @@ extern "C" {
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -79,24 +80,25 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
}
/* scene objects */
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *ob = base->object;
-
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
/* object itself */
- build_object(scene, base, ob);
+ build_object(scene, ob);
/* object that this is a proxy for */
// XXX: the way that proxies work needs to be completely reviewed!
if (ob->proxy) {
ob->proxy->proxy_from = ob;
- build_object(scene, base, ob->proxy);
+ build_object(scene, ob->proxy);
}
/* Object dupligroup. */
if (ob->dup_group) {
- build_group(scene, base, ob->dup_group);
+ build_group(scene, ob->dup_group);
}
}
+ FOREACH_SCENE_OBJECT_END
/* rigidbody */
if (scene->rigidbody_world) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 41d2ca0ca6d..6d4597fed9d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -129,8 +129,8 @@ static bool python_driver_depends_on_time(ChannelDriver *driver)
/* Function calls are considered dependent on a time. */
return true;
}
- if (strstr(driver->expression, "time") != NULL) {
- /* Variable `time` depends on time. */
+ if (strstr(driver->expression, "frame") != NULL) {
+ /* Variable `frame` depends on time. */
/* TODO(sergey): This is a bit weak, but not sure about better way of
* handling this.
*/
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 054e4103290..2e6fa7b5801 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -45,7 +45,7 @@
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_operation.h"
-struct Base;
+struct BaseLegacy;
struct bGPdata;
struct CacheFile;
struct ListBase;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
index 8a3476cff45..2f49d5b1645 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -46,6 +46,7 @@ extern "C" {
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -74,9 +75,9 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
}
/* scene objects */
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *ob = base->object;
-
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
/* object itself */
build_object(bmain, scene, ob);
@@ -97,6 +98,7 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
build_group(bmain, scene, ob, ob->dup_group);
}
}
+ FOREACH_SCENE_OBJECT_END
/* rigidbody */
if (scene->rigidbody_world) {
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 065f65659e6..3a042535d26 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -53,6 +53,7 @@ extern "C" {
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph.h"
+#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
/* Unfinished and unused, and takes quite some pre-processing time. */
@@ -362,6 +363,11 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
return;
}
+ DEG_DEBUG_PRINTF("%s: layers:%u, graph->layers:%u\n",
+ __func__,
+ layers,
+ graph->layers);
+
/* Set time for the current graph evaluation context. */
TimeSourceDepsNode *time_src = graph->find_time_source();
eval_ctx->ctime = time_src->cfra;
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 60449ebc600..d5b54e8a746 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -26,37 +26,53 @@
set(INC
.
intern
- nodes
- operations
+ engines/clay
+
../blenkernel
../blenlib
../blentranslation
../imbuf
+ ../depsgraph
../makesdna
../makesrna
- ../windowmanager
- ../nodes
- ../nodes/composite
- ../nodes/intern
+ ../gpu
+ ../editors/include
+ ../editors/space_view3d
../render/extern/include
../render/intern/include
- ../../../extern/clew/include
+
+ ../../../intern/glew-mx
../../../intern/guardedalloc
- ../../../intern/atomic
)
set(INC_SYS
-
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- DRW_defines.h
+ intern/draw_manager.c
+ intern/draw_mode_pass.c
+ intern/draw_cache.c
+ engines/clay/clay.c
-)
+ intern/DRW_render.h
+ intern/draw_mode_pass.h
+ intern/draw_cache.h
+ engines/clay/clay.h
-list(APPEND INC
+ ./DRW_engine.h
)
+if(WITH_CLAY_ENGINE)
+ add_definitions(-DWITH_CLAY_ENGINE)
endif()
+data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC)
+data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
+data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC)
+data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
+
+list(APPEND INC
+)
+
blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
new file mode 100644
index 00000000000..4f86e3fcd91
--- /dev/null
+++ b/source/blender/draw/DRW_engine.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file DRW_engine.h
+ * \ingroup draw
+ */
+
+#ifndef __DRW_ENGINE_H__
+#define __DRW_ENGINE_H__
+
+//#define WITH_VIEWPORT_CACHE_TEST
+
+struct DRWPass;
+struct Material;
+struct Scene;
+
+void DRW_engines_init(void);
+void DRW_engines_free(void);
+
+/* This is here because GPUViewport needs it */
+void DRW_pass_free(struct DRWPass *pass);
+
+/* Settings */
+void *DRW_material_settings_get(struct Material *ma, const char *engine_name);
+void *DRW_render_settings_get(struct Scene *scene, const char *engine_name);
+
+#endif /* __DRW_ENGINE_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/DRW_engines.h b/source/blender/draw/DRW_engines.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/source/blender/draw/DRW_engines.h
+++ /dev/null
diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c
new file mode 100644
index 00000000000..0572f4a0dc9
--- /dev/null
+++ b/source/blender/draw/engines/clay/clay.c
@@ -0,0 +1,776 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_icons.h"
+#include "BKE_main.h"
+
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "clay.h"
+#ifdef WITH_CLAY_ENGINE
+/* Shaders */
+
+#define CLAY_ENGINE "BLENDER_CLAY"
+
+extern char datatoc_clay_frag_glsl[];
+extern char datatoc_clay_vert_glsl[];
+extern char datatoc_ssao_alchemy_glsl[];
+extern char datatoc_ssao_groundtruth_glsl[];
+
+/* Storage */
+
+/* UBOs data needs to be 16 byte aligned (size of vec4) */
+/* Reminder : float, int, bool are 4 bytes */
+typedef struct CLAY_UBO_Material {
+ float ssao_params_var[4];
+ /* - 16 -*/
+ float matcap_hsv[3];
+ float matcap_id; /* even float encoding have enough precision */
+ /* - 16 -*/
+ float matcap_rot[2];
+ float pad[2]; /* ensure 16 bytes alignement */
+} CLAY_UBO_Material; /* 48 bytes */
+
+#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */
+
+typedef struct CLAY_UBO_Storage {
+ CLAY_UBO_Material materials[MAX_CLAY_MAT];
+} CLAY_UBO_Storage;
+
+static struct CLAY_data {
+ /* Depth Pre Pass */
+ struct GPUShader *depth_sh;
+ /* Shading Pass */
+ struct GPUShader *clay_sh;
+
+ /* Matcap textures */
+ struct GPUTexture *matcap_array;
+ float matcap_colors[24][3];
+
+ /* Ssao */
+ float winmat[4][4];
+ float viewvecs[3][4];
+ float ssao_params[4];
+ struct GPUTexture *jitter_tx;
+ struct GPUTexture *sampling_tx;
+} data = {NULL};
+
+/* GPUViewport.storage
+ * Is freed everytime the viewport engine changes */
+typedef struct CLAY_Storage {
+ /* Materials Parameter UBO */
+ CLAY_UBO_Storage mat_storage;
+ int ubo_current_id;
+ DRWShadingGroup *shgrps[MAX_CLAY_MAT];
+} CLAY_Storage;
+
+/* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
+static int ubo_mat_idxs[MAX_CLAY_MAT] = {0};
+
+/* keep it under MAX_STORAGE */
+typedef struct CLAY_StorageList {
+ struct CLAY_Storage *storage;
+ struct GPUUniformBuffer *mat_ubo;
+} CLAY_StorageList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct CLAY_FramebufferList{
+ /* default */
+ struct GPUFrameBuffer *default_fb;
+ /* engine specific */
+ struct GPUFrameBuffer *downsample_depth;
+} CLAY_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct CLAY_TextureList{
+ /* default */
+ struct GPUTexture *color;
+ struct GPUTexture *depth;
+ /* engine specific */
+ struct GPUTexture *depth_low;
+} CLAY_TextureList;
+
+/* for clarity follow the same layout as CLAY_TextureList */
+enum {
+ SCENE_COLOR,
+ SCENE_DEPTH,
+ SCENE_DEPTH_LOW,
+};
+
+/* keep it under MAX_PASSES */
+typedef struct CLAY_PassList{
+ /* default */
+ struct DRWPass *non_meshes_pass;
+ struct DRWPass *ob_center_pass;
+ /* engine specific */
+ struct DRWPass *depth_pass;
+ struct DRWPass *clay_pass;
+ struct DRWPass *wire_overlay_pass;
+ struct DRWPass *wire_outline_pass;
+} CLAY_PassList;
+
+//#define GTAO
+
+/* Functions */
+
+static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer)
+{
+ int image_size = prv->w[0] * prv->h[0];
+ float *new_rect = &final_rect[image_size * 4 * layer];
+
+ IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]);
+
+ /* Find overall color */
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
+ data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
+ data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
+ }
+ }
+
+ data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
+ data.matcap_colors[layer][1] /= 16.0f * 2.0f;
+ data.matcap_colors[layer][2] /= 16.0f * 2.0f;
+}
+
+static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr)
+{
+ struct GPUTexture *tex;
+ int w = prv[0]->w[0];
+ int h = prv[0]->h[0];
+ float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect");
+
+ for (int i = 0; i < nbr; ++i) {
+ add_icon_to_rect(prv[i], final_rect, i);
+ BKE_previewimg_free(&prv[i]);
+ }
+
+ tex = DRW_texture_create_2D_array(w, h, nbr, DRW_TEX_RGBA_8, DRW_TEX_FILTER, final_rect);
+ MEM_freeN(final_rect);
+
+ return tex;
+}
+
+static int matcap_to_index(int matcap)
+{
+ if (matcap == ICON_MATCAP_02) return 1;
+ else if (matcap == ICON_MATCAP_03) return 2;
+ else if (matcap == ICON_MATCAP_04) return 3;
+ else if (matcap == ICON_MATCAP_05) return 4;
+ else if (matcap == ICON_MATCAP_06) return 5;
+ else if (matcap == ICON_MATCAP_07) return 6;
+ else if (matcap == ICON_MATCAP_08) return 7;
+ else if (matcap == ICON_MATCAP_09) return 8;
+ else if (matcap == ICON_MATCAP_10) return 9;
+ else if (matcap == ICON_MATCAP_11) return 10;
+ else if (matcap == ICON_MATCAP_12) return 11;
+ else if (matcap == ICON_MATCAP_13) return 12;
+ else if (matcap == ICON_MATCAP_14) return 13;
+ else if (matcap == ICON_MATCAP_15) return 14;
+ else if (matcap == ICON_MATCAP_16) return 15;
+ else if (matcap == ICON_MATCAP_17) return 16;
+ else if (matcap == ICON_MATCAP_18) return 17;
+ else if (matcap == ICON_MATCAP_19) return 18;
+ else if (matcap == ICON_MATCAP_20) return 19;
+ else if (matcap == ICON_MATCAP_21) return 20;
+ else if (matcap == ICON_MATCAP_22) return 21;
+ else if (matcap == ICON_MATCAP_23) return 22;
+ else if (matcap == ICON_MATCAP_24) return 23;
+ return 0;
+}
+
+static struct GPUTexture *create_spiral_sample_texture(int numsaples)
+{
+ struct GPUTexture *tex;
+ float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
+ const float numsaples_inv = 1.0f / numsaples;
+ int i;
+ /* arbitrary number to ensure we don't get conciding samples every circle */
+ const float spirals = 7.357;
+
+ for (i = 0; i < numsaples; i++) {
+ float r = (i + 0.5f) * numsaples_inv;
+ float phi = r * spirals * (float)(2.0 * M_PI);
+ texels[i][0] = r * cosf(phi);
+ texels[i][1] = r * sinf(phi);
+ }
+
+ tex = DRW_texture_create_1D(numsaples, DRW_TEX_RG_16, 0, (float *)texels);
+
+ MEM_freeN(texels);
+ return tex;
+}
+
+static struct GPUTexture *create_jitter_texture(void)
+{
+ float jitter[64 * 64][2];
+ int i;
+
+ /* TODO replace by something more evenly distributed like blue noise */
+ for (i = 0; i < 64 * 64; i++) {
+#ifdef GTAO
+ jitter[i][0] = BLI_frand();
+ jitter[i][1] = BLI_frand();
+#else
+ jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
+ jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
+ normalize_v2(jitter[i]);
+#endif
+ }
+
+ return DRW_texture_create_2D(64, 64, DRW_TEX_RG_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
+}
+
+static void clay_material_settings_init(MaterialEngineSettingsClay *ma)
+{
+ ma->matcap_icon = ICON_MATCAP_01;
+ ma->matcap_rot = 0.0f;
+ ma->matcap_hue = 0.5f;
+ ma->matcap_sat = 0.5f;
+ ma->matcap_val = 0.5f;
+ ma->ssao_distance = 0.2;
+ ma->ssao_attenuation = 1.0f;
+ ma->ssao_factor_cavity = 1.0f;
+ ma->ssao_factor_edge = 1.0f;
+}
+
+RenderEngineSettings *CLAY_render_settings_create(void)
+{
+ RenderEngineSettingsClay *settings = MEM_callocN(sizeof(RenderEngineSettingsClay), "RenderEngineSettingsClay");
+
+ clay_material_settings_init((MaterialEngineSettingsClay *)settings);
+
+ settings->ssao_samples = 32;
+
+ return (RenderEngineSettings *)settings;
+}
+
+MaterialEngineSettings *CLAY_material_settings_create(void)
+{
+ MaterialEngineSettingsClay *settings = MEM_callocN(sizeof(MaterialEngineSettingsClay), "MaterialEngineSettingsClay");
+
+ clay_material_settings_init(settings);
+
+ return (MaterialEngineSettings *)settings;
+}
+
+static void CLAY_engine_init(CLAY_StorageList *stl)
+{
+ /* Create Texture Array */
+ if (!data.matcap_array) {
+ PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */
+
+ /* TODO only load used matcaps */
+ prv[0] = UI_icon_to_preview(ICON_MATCAP_01);
+ prv[1] = UI_icon_to_preview(ICON_MATCAP_02);
+ prv[2] = UI_icon_to_preview(ICON_MATCAP_03);
+ prv[3] = UI_icon_to_preview(ICON_MATCAP_04);
+ prv[4] = UI_icon_to_preview(ICON_MATCAP_05);
+ prv[5] = UI_icon_to_preview(ICON_MATCAP_06);
+ prv[6] = UI_icon_to_preview(ICON_MATCAP_07);
+ prv[7] = UI_icon_to_preview(ICON_MATCAP_08);
+ prv[8] = UI_icon_to_preview(ICON_MATCAP_09);
+ prv[9] = UI_icon_to_preview(ICON_MATCAP_10);
+ prv[10] = UI_icon_to_preview(ICON_MATCAP_11);
+ prv[11] = UI_icon_to_preview(ICON_MATCAP_12);
+ prv[12] = UI_icon_to_preview(ICON_MATCAP_13);
+ prv[13] = UI_icon_to_preview(ICON_MATCAP_14);
+ prv[14] = UI_icon_to_preview(ICON_MATCAP_15);
+ prv[15] = UI_icon_to_preview(ICON_MATCAP_16);
+ prv[16] = UI_icon_to_preview(ICON_MATCAP_17);
+ prv[17] = UI_icon_to_preview(ICON_MATCAP_18);
+ prv[18] = UI_icon_to_preview(ICON_MATCAP_19);
+ prv[19] = UI_icon_to_preview(ICON_MATCAP_20);
+ prv[20] = UI_icon_to_preview(ICON_MATCAP_21);
+ prv[21] = UI_icon_to_preview(ICON_MATCAP_22);
+ prv[22] = UI_icon_to_preview(ICON_MATCAP_23);
+ prv[23] = UI_icon_to_preview(ICON_MATCAP_24);
+
+ data.matcap_array = load_matcaps(prv, 24);
+ }
+
+ /* AO Jitter */
+ if (!data.jitter_tx) {
+ data.jitter_tx = create_jitter_texture();
+ }
+
+ /* AO Samples */
+ /* TODO use hammersley sequence */
+ if (!data.sampling_tx) {
+ data.sampling_tx = create_spiral_sample_texture(500);
+ }
+
+ /* Depth prepass */
+ if (!data.depth_sh) {
+ data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+
+ /* Shading pass */
+ if (!data.clay_sh) {
+ DynStr *ds = BLI_dynstr_new();
+ const char *max_mat =
+ "#define MAX_MATERIAL 512\n"
+ "#define USE_ROTATION\n"
+ "#define USE_AO\n"
+ "#define USE_HSV\n";
+ char *matcap_with_ao;
+
+ BLI_dynstr_append(ds, datatoc_clay_frag_glsl);
+#ifdef GTAO
+ BLI_dynstr_append(ds, datatoc_ssao_groundtruth_glsl);
+#else
+ BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl);
+#endif
+
+ matcap_with_ao = BLI_dynstr_get_cstring(ds);
+
+ data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat);
+
+ BLI_dynstr_free(ds);
+ MEM_freeN(matcap_with_ao);
+ }
+
+ if (!stl->storage) {
+ stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage");
+ }
+
+ if (!stl->mat_ubo) {
+ stl->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
+ }
+
+ if (ubo_mat_idxs[1] == 0) {
+ /* Just int to have pointers to them */
+ for (int i = 0; i < MAX_CLAY_MAT; ++i) {
+ ubo_mat_idxs[i] = i;
+ }
+ }
+}
+
+static void CLAY_ssao_setup(void)
+{
+ float invproj[4][4];
+ float dfdyfacs[2];
+ bool is_persp = DRW_viewport_is_persp_get();
+ /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
+ float viewvecs[3][4] = {
+ {-1.0f, -1.0f, -1.0f, 1.0f},
+ {1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f}
+ };
+ int i;
+ float *size = DRW_viewport_size_get();
+ RenderEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
+
+ DRW_get_dfdy_factors(dfdyfacs);
+
+ data.ssao_params[0] = settings->ssao_samples;
+ data.ssao_params[1] = size[0] / 64.0;
+ data.ssao_params[2] = size[1] / 64.0;
+ data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
+
+ /* invert the view matrix */
+ DRW_viewport_matrix_get(data.winmat, DRW_MAT_WIN);
+ invert_m4_m4(invproj, data.winmat);
+
+ /* convert the view vectors to view space */
+ for (i = 0; i < 3; i++) {
+ mul_m4_v4(invproj, viewvecs[i]);
+ /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+ if (is_persp)
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
+ viewvecs[i][3] = 1.0;
+
+ copy_v4_v4(data.viewvecs[i], viewvecs[i]);
+ }
+
+ /* we need to store the differences */
+ data.viewvecs[1][0] -= data.viewvecs[0][0];
+ data.viewvecs[1][1] = data.viewvecs[2][1] - data.viewvecs[0][1];
+
+ /* calculate a depth offset as well */
+ if (!is_persp) {
+ float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+ mul_m4_v4(invproj, vec_far);
+ mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+ data.viewvecs[1][2] = vec_far[2] - data.viewvecs[0][2];
+ }
+}
+
+static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *material_id)
+{
+ const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3;
+
+ //CLAY_UBO_Material *mat = &data.mat_storage.materials[0];
+ DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass);
+
+ DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH, depthloc);
+ DRW_shgroup_uniform_texture(grp, "matcaps", data.matcap_array, matcaploc);
+ DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)data.winmat);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)data.viewvecs, 3);
+ DRW_shgroup_uniform_vec4(grp, "ssao_params", data.ssao_params, 1);
+ DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)data.matcap_colors, 24);
+
+ DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
+
+#ifndef GTAO
+ DRW_shgroup_uniform_texture(grp, "ssao_jitter", data.jitter_tx, jitterloc);
+ DRW_shgroup_uniform_texture(grp, "ssao_samples", data.sampling_tx, sampleloc);
+#endif
+
+ return grp;
+}
+
+static int search_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
+ float matcap_val, float ssao_distance, float ssao_factor_cavity,
+ float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
+{
+ /* For now just use a linear search and test all parameters */
+ /* TODO make a hash table */
+ for (int i = 0; i < storage->ubo_current_id; ++i)
+ {
+ CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i];
+
+ if ((ubo->matcap_rot[0] == cosf(matcap_rot * 3.14159f * 2.0f)) &&
+ (ubo->matcap_hsv[0] == matcap_hue + 0.5f) &&
+ (ubo->matcap_hsv[1] == matcap_sat * 2.0f) &&
+ (ubo->matcap_hsv[2] == matcap_val * 2.0f) &&
+ (ubo->ssao_params_var[0] == ssao_distance) &&
+ (ubo->ssao_params_var[1] == ssao_factor_cavity) &&
+ (ubo->ssao_params_var[2] == ssao_factor_edge) &&
+ (ubo->ssao_params_var[3] == ssao_attenuation) &&
+ (ubo->matcap_id == matcap_to_index(matcap_icon)))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
+ float matcap_val, float ssao_distance, float ssao_factor_cavity,
+ float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
+{
+ int id = storage->ubo_current_id;
+ CLAY_UBO_Material *ubo = &storage->mat_storage.materials[id];
+
+ ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
+ ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
+
+ ubo->matcap_hsv[0] = matcap_hue + 0.5f;
+ ubo->matcap_hsv[1] = matcap_sat * 2.0f;
+ ubo->matcap_hsv[2] = matcap_val * 2.0f;
+
+ ubo->ssao_params_var[0] = ssao_distance;
+ ubo->ssao_params_var[1] = ssao_factor_cavity;
+ ubo->ssao_params_var[2] = ssao_factor_edge;
+ ubo->ssao_params_var[3] = ssao_attenuation;
+
+ ubo->matcap_id = matcap_to_index(matcap_icon);
+
+ storage->ubo_current_id++;
+
+ return id;
+}
+
+static int mat_in_ubo(CLAY_Storage *storage, struct GPUUniformBuffer *ubo, DRWPass *pass,
+ float matcap_rot, float matcap_hue, float matcap_sat,
+ float matcap_val, float ssao_distance, float ssao_factor_cavity,
+ float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
+{
+ int id;
+
+ /* Search material in UBO */
+ id = search_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
+ ssao_distance, ssao_factor_cavity, ssao_factor_edge,
+ ssao_attenuation, matcap_icon);
+
+ /* if not found create it */
+ if (id == -1) {
+ id = push_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
+ ssao_distance, ssao_factor_cavity, ssao_factor_edge,
+ ssao_attenuation, matcap_icon);
+
+ storage->shgrps[id] = CLAY_shgroup_create(pass, &ubo_mat_idxs[id]);
+
+ /* if it's the first shgrp, pass bind the material UBO */
+ if (storage->ubo_current_id == 1) {
+ DRW_shgroup_uniform_block(storage->shgrps[0], "material_block", ubo, 0);
+ }
+ }
+
+ return id;
+}
+
+/* Safe way to get override values */
+static void override_setting(CollectionEngineSettings *ces, const char *name, void *ret)
+{
+ CollectionEngineProperty *cep = BKE_collection_engine_property_get(ces, name);
+
+ if (cep == NULL) {
+ return;
+ }
+
+ if ((cep->flag & COLLECTION_PROP_USE) == 0) {
+ return;
+ }
+
+ if (cep->type == COLLECTION_PROP_TYPE_INT) {
+ CollectionEnginePropertyInt *prop = (CollectionEnginePropertyInt *)cep;
+ *((int *)ret) = prop->value;
+ }
+ else {
+ CollectionEnginePropertyFloat *prop = (CollectionEnginePropertyFloat *)cep;
+ *((float *)ret) = prop->value;
+ }
+}
+
+static DRWShadingGroup *CLAY_object_shgrp_get(Object *ob, CLAY_StorageList *stl, DRWPass *pass)
+{
+ MaterialEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
+ CollectionEngineSettings *ces = ob->collection_settings;
+
+ /* Default Settings */
+ float matcap_rot = settings->matcap_rot;
+ float matcap_hue = settings->matcap_hue;
+ float matcap_sat = settings->matcap_sat;
+ float matcap_val = settings->matcap_val;
+ float ssao_distance = settings->ssao_distance;
+ float ssao_factor_cavity = settings->ssao_factor_cavity;
+ float ssao_factor_edge = settings->ssao_factor_edge;
+ float ssao_attenuation = settings->ssao_attenuation;
+ int matcap_icon = settings->matcap_icon;
+
+ /* Override settings */
+ if (ces) {
+ override_setting(ces, "matcap_rotation", &matcap_rot);
+ override_setting(ces, "matcap_hue", &matcap_hue);
+ override_setting(ces, "matcap_saturation", &matcap_sat);
+ override_setting(ces, "matcap_value", &matcap_val);
+ override_setting(ces, "ssao_distance", &ssao_distance);
+ override_setting(ces, "ssao_factor_cavity", &ssao_factor_cavity);
+ override_setting(ces, "ssao_factor_edge", &ssao_factor_edge);
+ override_setting(ces, "ssao_attenuation", &ssao_attenuation);
+ override_setting(ces, "matcap_icon", &matcap_icon);
+ };
+
+
+ int index = mat_in_ubo(stl->storage, stl->mat_ubo, pass,
+ matcap_rot, matcap_hue, matcap_sat, matcap_val,
+ ssao_distance, ssao_factor_cavity, ssao_factor_edge,
+ ssao_attenuation, matcap_icon);
+
+ return stl->storage->shgrps[index];
+}
+
+static void CLAY_create_cache(CLAY_PassList *passes, CLAY_StorageList *stl, const struct bContext *C)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ DRWShadingGroup *clay_shgrp;
+ DRWShadingGroup *depth_shgrp;
+
+ /* Depth Pass */
+ {
+ passes->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ depth_shgrp = DRW_shgroup_create(data.depth_sh, passes->depth_pass);
+ }
+
+ /* Clay Pass */
+ {
+ passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS);
+ stl->storage->ubo_current_id = 0;
+ }
+
+ /* Object Mode */
+ {
+ DRW_pass_setup_common(&passes->wire_overlay_pass,
+ &passes->wire_outline_pass,
+ &passes->non_meshes_pass,
+ &passes->ob_center_pass);
+ }
+
+ /* TODO Create hash table of batch based on material id*/
+ Object *ob;
+ DEG_OBJECT_ITER(sl, CLAY_ENGINE, ob);
+ {
+ if ((ob->base_flag & BASE_VISIBLED) == 0) {
+ continue;
+ }
+
+ struct Batch *geom;
+ //bool do_outlines;
+
+ switch (ob->type) {
+ case OB_MESH:
+ clay_shgrp = CLAY_object_shgrp_get(ob, stl, passes->clay_pass);
+ geom = DRW_cache_surface_get(ob);
+
+ /* Add everything for now */
+ DRW_shgroup_call_add(depth_shgrp, geom, ob->obmat);
+
+ if (clay_shgrp)
+ DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
+
+ //DRW_shgroup_wire_overlay(passes->wire_overlay_pass, ob);
+
+ //do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
+ //DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines);
+
+ /* When encountering a new material :
+ * - Create new Batch
+ * - Initialize Batch
+ * - Push it to the hash table
+ * - The pass takes care of inserting it
+ * next to the same shader calls */
+
+ /* Free hash table */
+ break;
+ case OB_LAMP:
+ case OB_CAMERA:
+ case OB_EMPTY:
+ default:
+ DRW_shgroup_non_meshes(passes->non_meshes_pass, ob);
+ break;
+ }
+
+ DRW_shgroup_object_center(passes->ob_center_pass, ob);
+ DRW_shgroup_relationship_lines(passes->non_meshes_pass, ob);
+ }
+ DEG_OBJECT_ITER_END
+
+ DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage);
+}
+
+static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context)
+{
+ /* This function may run for multiple viewports
+ * so get the current viewport buffers */
+ CLAY_FramebufferList *buffers = NULL;
+ CLAY_TextureList *textures = NULL;
+ CLAY_PassList *passes = NULL;
+ CLAY_StorageList *storage = NULL;
+
+ DRW_viewport_init(context, (void **)&buffers, (void **)&textures, (void **)&passes, (void **)&storage);
+
+ CLAY_engine_init(storage);
+
+ /* TODO : tag to refresh by the deps graph */
+ /* ideally only refresh when objects are added/removed */
+ /* or render properties / materials change */
+#ifdef WITH_VIEWPORT_CACHE_TEST
+ static bool once = false;
+#endif
+ if (DRW_viewport_cache_is_dirty()
+#ifdef WITH_VIEWPORT_CACHE_TEST
+ && !once
+#endif
+ ) {
+#ifdef WITH_VIEWPORT_CACHE_TEST
+ once = true;
+#endif
+ CLAY_create_cache(passes, storage, context);
+ }
+
+ /* Start Drawing */
+ DRW_draw_background();
+
+ /* Pass 1 : Depth pre-pass */
+ DRW_draw_pass(passes->depth_pass);
+
+ /* Pass 2 (Optionnal) : Separated Downsampled AO */
+ DRW_framebuffer_texture_detach(textures->depth);
+ /* TODO */
+
+ /* Pass 3 : Shading */
+ CLAY_ssao_setup();
+ DRW_draw_pass(passes->clay_pass);
+
+ /* Pass 4 : Overlays */
+ DRW_framebuffer_texture_attach(buffers->default_fb, textures->depth, 0);
+ //DRW_draw_pass(passes->wire_overlay_pass);
+ //DRW_draw_pass(passes->wire_outline_pass);
+ DRW_draw_pass(passes->non_meshes_pass);
+ DRW_draw_pass(passes->ob_center_pass);
+
+ /* Always finish by this */
+ DRW_state_reset();
+}
+
+static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ BKE_collection_engine_property_add_int(ces, "matcap_icon", ICON_MATCAP_01);
+ BKE_collection_engine_property_add_int(ces, "type", CLAY_MATCAP_NONE);
+ BKE_collection_engine_property_add_float(ces, "matcap_rotation", 0.0f);
+ BKE_collection_engine_property_add_float(ces, "matcap_hue", 0.5f);
+ BKE_collection_engine_property_add_float(ces, "matcap_saturation", 0.5f);
+ BKE_collection_engine_property_add_float(ces, "matcap_value", 0.5f);
+ BKE_collection_engine_property_add_float(ces, "ssao_distance", 0.2f);
+ BKE_collection_engine_property_add_float(ces, "ssao_attenuation", 1.0f);
+ BKE_collection_engine_property_add_float(ces, "ssao_factor_cavity", 1.0f);
+ BKE_collection_engine_property_add_float(ces, "ssao_factor_edge", 1.0f);
+}
+
+void clay_engine_free(void)
+{
+ /* data.depth_sh Is builtin so it's automaticaly freed */
+ if (data.clay_sh) {
+ DRW_shader_free(data.clay_sh);
+ }
+
+ if (data.matcap_array) {
+ DRW_texture_free(data.matcap_array);
+ }
+
+ if (data.jitter_tx) {
+ DRW_texture_free(data.jitter_tx);
+ }
+
+ if (data.sampling_tx) {
+ DRW_texture_free(data.sampling_tx);
+ }
+}
+
+RenderEngineType viewport_clay_type = {
+ NULL, NULL,
+ CLAY_ENGINE, N_("Clay"), RE_INTERNAL | RE_USE_OGL_PIPELINE,
+ NULL, NULL, NULL, NULL, &CLAY_view_draw, NULL, &CLAY_collection_settings_create,
+ {NULL, NULL, NULL}
+};
+
+
+#undef CLAY_ENGINE
+
+#endif
diff --git a/source/blender/draw/DRW_defines.h b/source/blender/draw/engines/clay/clay.h
index 212c39e203b..404924be2a1 100644
--- a/source/blender/draw/DRW_defines.h
+++ b/source/blender/draw/engines/clay/clay.h
@@ -19,7 +19,18 @@
*
*/
-#ifndef __DRW_DEFINES_H__
-#define __DRW_DEFINES_H__
+/** \file clay.h
+ * \ingroup DNA
+ */
+
+#ifndef __ENGINE_CLAY_H__
+#define __ENGINE_CLAY_H__
+
+extern RenderEngineType viewport_clay_type;
+
+struct RenderEngineSettings *CLAY_render_settings_create(void);
+struct MaterialEngineSettings *CLAY_material_settings_create(void);
+
+void clay_engine_free(void);
-#endif /* __DRW_DEFINES_H__ */
+#endif /* __ENGINE_CLAY_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
new file mode 100644
index 00000000000..7a38db35bcf
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
@@ -0,0 +1,205 @@
+uniform vec2 screenres;
+uniform sampler2D depthtex;
+uniform mat4 WinMatrix;
+
+/* Matcap */
+uniform sampler2DArray matcaps;
+uniform vec3 matcaps_color[24];
+
+/* Screen Space Occlusion */
+/* store the view space vectors for the corners of the view frustum here.
+ * It helps to quickly reconstruct view space vectors by using uv coordinates,
+ * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+uniform vec4 viewvecs[3];
+uniform vec4 ssao_params;
+
+uniform sampler2D ssao_jitter;
+uniform sampler1D ssao_samples;
+
+/* Material Parameters packed in an UBO */
+struct Material {
+ vec4 ssao_params_var;
+ vec4 matcap_hsv_id;
+ vec4 matcap_rot; /* vec4 to ensure 16 bytes alignement (don't trust compiler) */
+};
+
+layout(std140) uniform material_block {
+ Material matcaps_param[MAX_MATERIAL];
+};
+
+uniform int mat_id;
+
+/* Aliases */
+#define ssao_samples_num ssao_params.x
+#define jitter_tilling ssao_params.yz
+#define dfdy_sign ssao_params.w
+
+#define matcap_hsv matcaps_param[mat_id].matcap_hsv_id.xyz
+#define matcap_index matcaps_param[mat_id].matcap_hsv_id.w
+#define matcap_rotation matcaps_param[mat_id].matcap_rot.xy
+
+in vec3 normal;
+out vec4 fragColor;
+
+/* TODO Move this to SSAO modules */
+/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
+ * we change the factors from the article to fit the OpennGL model. */
+vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
+{
+ if (WinMatrix[3][3] == 0.0) {
+ /* Perspective */
+ float d = 2.0 * depth - 1.0;
+
+ float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]);
+
+ return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz);
+ }
+ else {
+ /* Orthographic */
+ vec3 offset = vec3(uvcoords, depth);
+
+ return viewvecs[0].xyz + offset * viewvecs[1].xyz;
+ }
+}
+
+/* TODO remove this when switching to geometric normals */
+vec3 calculate_view_space_normal(in vec3 viewposition)
+{
+ vec3 normal = cross(normalize(dFdx(viewposition)), dfdy_sign * normalize(dFdy(viewposition)));
+ return normalize(normal);
+}
+
+#ifdef USE_HSV
+void rgb_to_hsv(vec3 rgb, out vec3 outcol)
+{
+ float cmax, cmin, h, s, v, cdelta;
+ vec3 c;
+
+ cmax = max(rgb[0], max(rgb[1], rgb[2]));
+ cmin = min(rgb[0], min(rgb[1], rgb[2]));
+ cdelta = cmax - cmin;
+
+ v = cmax;
+ if (cmax != 0.0)
+ s = cdelta / cmax;
+ else {
+ s = 0.0;
+ h = 0.0;
+ }
+
+ if (s == 0.0) {
+ h = 0.0;
+ }
+ else {
+ c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta;
+
+ if (rgb.x == cmax) h = c[2] - c[1];
+ else if (rgb.y == cmax) h = 2.0 + c[0] - c[2];
+ else h = 4.0 + c[1] - c[0];
+
+ h /= 6.0;
+
+ if (h < 0.0)
+ h += 1.0;
+ }
+
+ outcol = vec3(h, s, v);
+}
+
+void hsv_to_rgb(vec3 hsv, out vec3 outcol)
+{
+ float i, f, p, q, t, h, s, v;
+ vec3 rgb;
+
+ h = hsv[0];
+ s = hsv[1];
+ v = hsv[2];
+
+ if (s == 0.0) {
+ rgb = vec3(v, v, v);
+ }
+ else {
+ if (h == 1.0)
+ h = 0.0;
+
+ h *= 6.0;
+ i = floor(h);
+ f = h - i;
+ rgb = vec3(f, f, f);
+ p = v * (1.0 - s);
+ q = v * (1.0 - (s * f));
+ t = v * (1.0 - (s * (1.0 - f)));
+
+ if (i == 0.0) rgb = vec3(v, t, p);
+ else if (i == 1.0) rgb = vec3(q, v, p);
+ else if (i == 2.0) rgb = vec3(p, v, t);
+ else if (i == 3.0) rgb = vec3(p, q, v);
+ else if (i == 4.0) rgb = vec3(t, p, v);
+ else rgb = vec3(v, p, q);
+ }
+
+ outcol = rgb;
+}
+
+void hue_sat(float hue, float sat, float value, inout vec3 col)
+{
+ vec3 hsv;
+
+ rgb_to_hsv(col, hsv);
+
+ hsv.x += hue;
+ hsv.x -= floor(hsv.x);
+ hsv.y *= sat;
+ hsv.y = clamp(hsv.y, 0.0, 1.0);
+ hsv.z *= value;
+ hsv.z = clamp(hsv.z, 0.0, 1.0);
+
+ hsv_to_rgb(hsv, col);
+}
+#endif
+
+#ifdef USE_AO
+/* Prototype */
+void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges);
+#endif
+
+void main() {
+ vec2 screenco = vec2(gl_FragCoord.xy) / screenres;
+ float depth = texture(depthtex, screenco).r;
+
+ vec3 position = get_view_space_from_depth(screenco, depth);
+ vec3 normal = calculate_view_space_normal(position);
+
+ /* Manual Depth test */
+ /* Doing this test earlier gives problem with dfdx calculations
+ * TODO move this before when we have proper geometric normals */
+ if (gl_FragCoord.z > depth + 1e-5)
+ discard;
+
+#ifdef USE_ROTATION
+ /* Rotate texture coordinates */
+ vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x);
+ vec2 texco = abs(vec2(dot(normal.xy, matcap_rotation), dot(normal.xy, rotY)) * .49 + 0.5);
+#else
+ vec2 texco = abs(normal.xy * .49 + 0.5);
+#endif
+ vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb;
+
+#ifdef USE_AO
+ float cavity, edges;
+ ssao_factors(depth, normal, position, screenco, cavity, edges);
+
+ col *= mix(vec3(1.0), matcaps_color[int(matcap_index)], cavity);
+#endif
+
+#ifdef USE_HSV
+ hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col);
+#endif
+
+#ifdef USE_AO
+ /* Apply highlights after hue shift */
+ col *= edges + 1.0;
+#endif
+
+ fragColor = vec4(col, 1.0);
+}
diff --git a/source/blender/draw/engines/clay/shaders/clay_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_vert.glsl
new file mode 100644
index 00000000000..0b598ea0291
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_vert.glsl
@@ -0,0 +1,20 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+#if __VERSION__ == 120
+attribute vec3 pos;
+attribute vec3 nor;
+varying vec3 normal;
+#else
+in vec3 pos;
+in vec3 nor;
+out vec3 normal;
+#endif
+
+
+void main()
+{
+ normal = normalize(NormalMatrix * nor);
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
+
diff --git a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
new file mode 100644
index 00000000000..d032fb91c01
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
@@ -0,0 +1,73 @@
+#define ssao_distance matcaps_param[mat_id].ssao_params_var.x
+#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y
+#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z
+#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w
+
+/* from The Alchemy screen-space ambient obscurance algorithm
+ * http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */
+
+void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges)
+{
+ /* take the normalized ray direction here */
+ vec2 rotX = texture2D(ssao_jitter, screenco.xy * jitter_tilling).rg;
+ vec2 rotY = vec2(-rotX.y, rotX.x);
+
+ /* find the offset in screen space by multiplying a point
+ * in camera space at the depth of the point by the projection matrix. */
+ vec2 offset;
+ float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3];
+ offset.x = WinMatrix[0][0] * ssao_distance / homcoord;
+ offset.y = WinMatrix[1][1] * ssao_distance / homcoord;
+ /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
+ offset *= 0.5;
+
+ cavities = edges = 0.0;
+ int x;
+ int num_samples = int(ssao_samples_num);
+
+ for (x = 0; x < num_samples; x++) {
+ /* TODO : optimisation replace by constant */
+ vec2 dir_sample = texture1D(ssao_samples, (float(x) + 0.5) / ssao_samples_num).rg;
+
+ /* rotate with random direction to get jittered result */
+ vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
+
+ vec2 uvcoords = screenco.xy + dir_jittered * offset;
+
+ if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
+ continue;
+
+ float depth_new = texture2D(depthtex, uvcoords).r;
+
+ /* Handle Background case */
+ bool is_background = (depth_new == 1.0);
+
+ /* This trick provide good edge effect even if no neighboor is found. */
+ vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new);
+
+ if (is_background)
+ pos_new.z -= ssao_distance;
+
+ vec3 dir = pos_new - position;
+ float len = length(dir);
+ float f_cavities = dot(dir, normal);
+ float f_edge = -f_cavities;
+ float f_bias = 0.05 * len + 0.0001;
+
+ float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation));
+
+ /* use minor bias here to avoid self shadowing */
+ if (f_cavities > -f_bias)
+ cavities += f_cavities * attenuation;
+
+ if (f_edge > f_bias)
+ edges += f_edge * attenuation;
+ }
+
+ cavities /= ssao_samples_num;
+ edges /= ssao_samples_num;
+
+ /* don't let cavity wash out the surface appearance */
+ cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0);
+ edges = edges * ssao_factor_edge;
+}
diff --git a/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl
new file mode 100644
index 00000000000..2f29624824e
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl
@@ -0,0 +1,120 @@
+#define ssao_distance matcaps_param[mat_id].ssao_params_var.x
+#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y
+#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z
+#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w
+
+/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion
+ * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
+ * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */
+
+#define COSINE_WEIGHTING
+
+float integrate_arc(in float h1, in float h2, in float gamma, in float n_proj_len)
+{
+ float a = 0.0;
+#ifdef COSINE_WEIGHTING
+ float cos_gamma = cos(gamma);
+ float sin_gamma_2 = 2.0 * sin(gamma);
+ a += -cos(2.0 * h1 - gamma) + cos_gamma + h1 * sin_gamma_2;
+ a += -cos(2.0 * h2 - gamma) + cos_gamma + h2 * sin_gamma_2;
+ a *= 0.25; /* 1/4 */
+ a *= n_proj_len;
+#else
+ /* Uniform weighting (slide 59) */
+ a += 1 - cos(h1);
+ a += 1 - cos(h2);
+#endif
+ return a;
+}
+
+float get_max_horizon(in vec2 co, in vec3 x, in vec3 omega_o, in float h)
+{
+ if (co.x > 1.0 || co.x < 0.0 || co.y > 1.0 || co.y < 0.0)
+ return h;
+
+ float depth = texture2D(depthtex, co).r;
+
+ /* Background case */
+ if (depth == 1.0)
+ return h;
+
+ vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */
+ vec3 omega_s = s - x;
+ float len = length(omega_s);
+
+ if (len < ssao_distance) {
+ omega_s /= len;
+ h = max(h, dot(omega_s, omega_o));
+ }
+ return h;
+}
+
+void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges)
+{
+ /* Renaming */
+ vec3 omega_o = -normalize(position); /* viewvec */
+ vec2 x_ = screenco; /* x^ Screen coordinate */
+ vec3 x = position; /* x view space coordinate */
+
+#ifdef SPATIAL_DENOISE
+ float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
+ float noise_offset = (1.0 / 4.0) * float(int(gl_FragCoord.y - gl_FragCoord.x) & 0x3);
+#else
+ float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
+ float noise_offset = (0.5 / 16.0) + (1.0 / 16.0) * float(((int(gl_FragCoord.x - gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
+#endif
+
+ const float phi_step = 16.0;
+ const float theta_step = 16.0;
+ const float m_pi = 3.14159265358979323846;
+ vec2 pixel_ratio = vec2(screenres.y / screenres.x, 1.0);
+ vec2 pixel_size = vec2(1.0) / screenres.xy;
+ float min_stride = length(pixel_size);
+ float homcco = WinMatrix[2][3] * position.z + WinMatrix[3][3];
+ float n = max(min_stride * theta_step, ssao_distance / homcco); /* Search distance */
+
+ /* Integral over PI */
+ float A = 0.0;
+ for (float i = 0.0; i < phi_step; i++) {
+ float phi = m_pi * ((noise_dir + i) / phi_step);
+
+ vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
+
+ /* Search maximum horizon angles Theta1 and Theta2 */
+ float theta1 = -1.0, theta2 = -1.0; /* init at cos(pi) */
+ for (float j = 0.0; j < theta_step; j++) {
+ vec2 s_ = t_phi * pixel_ratio * n * ((j + noise_offset)/ theta_step); /* s^ Screen coordinate */
+ vec2 co;
+
+ co = x_ + s_;
+ theta1 = get_max_horizon(co, x, omega_o, theta1);
+
+ co = x_ - s_;
+ theta2 = get_max_horizon(co, x, omega_o, theta2);
+ }
+
+ /* (Slide 54) */
+ theta1 = -acos(theta1);
+ theta2 = acos(theta2);
+
+ /* Projecting Normal to Plane P defined by t_phi and omega_o */
+ vec3 h = normalize(cross(vec3(t_phi, 0.0), omega_o)); /* Normal vector to Integration plane */
+ vec3 t = cross(h, omega_o); /* Normal vector to plane */
+ vec3 n_proj = normal - h * dot(normal, h);
+ float n_proj_len = length(n_proj);
+ vec3 n_proj_norm = normalize(n_proj);
+
+ /* Clamping thetas (slide 58) */
+ float gamma = sign(dot(n_proj_norm, t)) * acos(dot(normal, omega_o)); /* Angle between view vec and normal */
+ theta1 = gamma + max(theta1 - gamma, -m_pi * 0.5);
+ theta2 = gamma + min(theta2 - gamma, m_pi * 0.5);
+
+ /* Solving inner integral */
+ A += integrate_arc(theta1, theta2, gamma, n_proj_len);
+ }
+
+ A /= phi_step;
+
+ cavities = 1.0 - A;
+ edges = 0.0;
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
new file mode 100644
index 00000000000..78edae803b5
--- /dev/null
+++ b/source/blender/draw/intern/DRW_render.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file DRW_render.h
+ * \ingroup draw
+ */
+
+/* This is the Render Functions used by Realtime engines to draw with OpenGL */
+
+#ifndef __DRW_RENDER_H__
+#define __DRW_RENDER_H__
+
+#include "BKE_context.h"
+#include "BKE_layer.h"
+#include "BKE_scene.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math_matrix.h"
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+
+#include "draw_mode_pass.h"
+#include "draw_cache.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RE_engine.h"
+
+//#define WITH_VIEWPORT_CACHE_TEST
+
+struct GPUFrameBuffer;
+struct GPUShader;
+struct GPUTexture;
+struct GPUUniformBuffer;
+struct Object;
+struct Batch;
+
+typedef struct DRWUniform DRWUniform;
+typedef struct DRWInterface DRWInterface;
+typedef struct DRWPass DRWPass;
+typedef struct DRWShadingGroup DRWShadingGroup;
+
+/* Textures */
+
+typedef enum {
+ DRW_TEX_RGBA_8,
+ DRW_TEX_RGBA_16,
+ DRW_TEX_RGBA_32,
+ DRW_TEX_RGB_8,
+ DRW_TEX_RGB_16,
+ DRW_TEX_RGB_32,
+ DRW_TEX_RG_8,
+ DRW_TEX_RG_16,
+ DRW_TEX_RG_32,
+ DRW_TEX_R_8,
+ DRW_TEX_R_16,
+ DRW_TEX_R_32,
+ DRW_TEX_DEPTH_16,
+ DRW_TEX_DEPTH_24,
+ DRW_TEX_DEPTH_32,
+} DRWTextureFormat;
+
+typedef enum {
+ DRW_TEX_FILTER = (1 << 0),
+ DRW_TEX_WRAP = (1 << 1),
+ DRW_TEX_COMPARE = (1 << 2),
+} DRWTextureFlag;
+
+struct GPUTexture *DRW_texture_create_1D(
+ int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+struct GPUTexture *DRW_texture_create_2D(
+ int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+struct GPUTexture *DRW_texture_create_2D_array(
+ int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels);
+void DRW_texture_free(struct GPUTexture *tex);
+
+/* UBOs */
+struct GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data);
+void DRW_uniformbuffer_update(struct GPUUniformBuffer *ubo, const void *data);
+void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
+
+/* Buffers */
+
+/* DRWFboTexture->format */
+#define DRW_BUF_DEPTH_16 1
+#define DRW_BUF_DEPTH_24 2
+#define DRW_BUF_R_8 3
+#define DRW_BUF_R_16 4
+#define DRW_BUF_R_32 5
+#define DRW_BUF_RG_8 6
+#define DRW_BUF_RG_16 7
+#define DRW_BUF_RG_32 8
+#define DRW_BUF_RGB_8 9
+#define DRW_BUF_RGB_16 10
+#define DRW_BUF_RGB_32 11
+#define DRW_BUF_RGBA_8 12
+#define DRW_BUF_RGBA_16 13
+#define DRW_BUF_RGBA_32 14
+
+#define MAX_FBO_TEX 5
+
+typedef struct DRWFboTexture {
+ struct GPUTexture **tex;
+ int format;
+} DRWFboTexture;
+
+void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr);
+void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
+void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
+void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
+/* Shaders */
+struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_3D_depth_only(void);
+void DRW_shader_free(struct GPUShader *shader);
+
+/* Batches */
+
+typedef enum {
+ DRW_STATE_WRITE_DEPTH = (1 << 0),
+ DRW_STATE_WRITE_COLOR = (1 << 1),
+ DRW_STATE_DEPTH_LESS = (1 << 2),
+ DRW_STATE_DEPTH_EQUAL = (1 << 3),
+ DRW_STATE_CULL_BACK = (1 << 4),
+ DRW_STATE_CULL_FRONT = (1 << 5),
+ DRW_STATE_WIRE = (1 << 6),
+ DRW_STATE_WIRE_LARGE = (1 << 7),
+ DRW_STATE_POINT = (1 << 8),
+ DRW_STATE_STIPPLE_2 = (1 << 9),
+ DRW_STATE_STIPPLE_3 = (1 << 10),
+ DRW_STATE_STIPPLE_4 = (1 << 11),
+ DRW_STATE_BLEND = (1 << 12),
+} DRWState;
+
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, struct Batch *geom);
+DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass);
+
+void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Batch *geom, float (*obmat)[4]);
+void DRW_shgroup_dynamic_call_add(DRWShadingGroup *shgroup, ...);
+void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state);
+void DRW_shgroup_attrib_int(DRWShadingGroup *shgroup, const char *name, int size);
+void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size);
+
+void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex, int loc);
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo, int loc);
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc);
+void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize);
+void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
+void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
+void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
+void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value);
+void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value);
+
+/* Passes */
+DRWPass *DRW_pass_create(const char *name, DRWState state);
+
+/* Viewport */
+typedef enum {
+ DRW_MAT_PERS,
+ DRW_MAT_WIEW,
+ DRW_MAT_WIN,
+} DRWViewportMatrixType;
+
+void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes, void **storage);
+void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
+float *DRW_viewport_size_get(void);
+float *DRW_viewport_screenvecs_get(void);
+float *DRW_viewport_pixelsize_get(void);
+bool DRW_viewport_is_persp_get(void);
+bool DRW_viewport_cache_is_dirty(void);
+
+/* Settings */
+#ifndef __DRW_ENGINE_H__
+void *DRW_material_settings_get(Material *ma, const char *engine_name);
+void *DRW_render_settings_get(Scene *scene, const char *engine_name);
+#endif /* __DRW_ENGINE_H__ */
+
+/* Draw commands */
+void DRW_draw_background(void);
+void DRW_centercircle(const float co[3]);
+void DRW_draw_pass(DRWPass *pass);
+
+void DRW_state_reset(void);
+
+/* Other */
+void DRW_get_dfdy_factors(float dfdyfac[2]);
+
+#endif /* __DRW_RENDER_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
new file mode 100644
index 00000000000..7ea6b8d0066
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache.c
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_cache.c
+ * \ingroup draw
+ */
+
+
+#include "DNA_scene_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BKE_mesh_render.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache.h"
+
+static struct DRWShapeCache{
+ Batch *drw_single_vertice;
+ Batch *drw_fullscreen_quad;
+ Batch *drw_plain_axes;
+ Batch *drw_single_arrow;
+ Batch *drw_cube;
+ Batch *drw_circle;
+ Batch *drw_line;
+ Batch *drw_empty_sphere;
+ Batch *drw_empty_cone;
+ Batch *drw_arrows;
+ Batch *drw_lamp;
+ Batch *drw_lamp_sunrays;
+} SHC = {NULL};
+
+void DRW_shape_cache_free(void)
+{
+ if (SHC.drw_single_vertice)
+ Batch_discard_all(SHC.drw_single_vertice);
+ if (SHC.drw_fullscreen_quad)
+ Batch_discard_all(SHC.drw_fullscreen_quad);
+ if (SHC.drw_plain_axes)
+ Batch_discard_all(SHC.drw_plain_axes);
+ if (SHC.drw_single_arrow)
+ Batch_discard_all(SHC.drw_single_arrow);
+ if (SHC.drw_cube)
+ Batch_discard_all(SHC.drw_cube);
+ if (SHC.drw_circle)
+ Batch_discard_all(SHC.drw_circle);
+ if (SHC.drw_line)
+ Batch_discard_all(SHC.drw_line);
+ if (SHC.drw_empty_sphere)
+ Batch_discard_all(SHC.drw_empty_sphere);
+ if (SHC.drw_empty_cone)
+ Batch_discard_all(SHC.drw_empty_cone);
+ if (SHC.drw_arrows)
+ Batch_discard_all(SHC.drw_arrows);
+ if (SHC.drw_lamp)
+ Batch_discard_all(SHC.drw_lamp);
+ if (SHC.drw_lamp_sunrays)
+ Batch_discard_all(SHC.drw_lamp_sunrays);
+}
+
+/* Quads */
+Batch *DRW_cache_fullscreen_quad_get(void)
+{
+ if (!SHC.drw_fullscreen_quad) {
+ float v1[2] = {-1.0f, -1.0f};
+ float v2[2] = { 1.0f, -1.0f};
+ float v3[2] = {-1.0f, 1.0f};
+ float v4[2] = { 1.0f, 1.0f};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 6);
+
+ setAttrib(vbo, pos_id, 0, v1);
+ setAttrib(vbo, pos_id, 1, v2);
+ setAttrib(vbo, pos_id, 2, v3);
+
+ setAttrib(vbo, pos_id, 3, v2);
+ setAttrib(vbo, pos_id, 4, v3);
+ setAttrib(vbo, pos_id, 5, v4);
+
+ SHC.drw_fullscreen_quad = Batch_create(GL_TRIANGLES, vbo, NULL);
+ }
+ return SHC.drw_fullscreen_quad;
+}
+
+/* Common */
+
+Batch *DRW_cache_cube_get(void)
+{
+ if (!SHC.drw_cube) {
+ const GLfloat verts[8][3] = {
+ {-1.0f, -1.0f, -1.0f},
+ {-1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f},
+ {-1.0f, 1.0f, 1.0f},
+ { 1.0f, -1.0f, -1.0f},
+ { 1.0f, -1.0f, 1.0f},
+ { 1.0f, 1.0f, -1.0f},
+ { 1.0f, 1.0f, 1.0f}
+ };
+
+ 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};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 24);
+
+ for (int i = 0; i < 24; ++i) {
+ setAttrib(vbo, pos_id, i, verts[indices[i]]);
+ }
+
+ SHC.drw_cube = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_cube;
+}
+
+Batch *DRW_cache_circle_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_circle) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2);
+
+ for (int a = 0; a < CIRCLE_RESOL; a++) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[2] = 0.0f;
+ setAttrib(vbo, pos_id, a * 2, v);
+
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[2] = 0.0f;
+ setAttrib(vbo, pos_id, a * 2 + 1, v);
+ }
+
+ SHC.drw_circle = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_circle;
+#undef CIRCLE_RESOL
+}
+
+Batch *DRW_cache_single_line_get(void)
+{
+ /* Z axis line */
+ if (!SHC.drw_line) {
+ float v1[3] = {0.0f, 0.0f, 0.0f};
+ float v2[3] = {0.0f, 0.0f, 1.0f};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 2);
+
+ setAttrib(vbo, pos_id, 0, v1);
+ setAttrib(vbo, pos_id, 1, v2);
+
+ SHC.drw_line = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_line;
+}
+
+/* Empties */
+Batch *DRW_cache_plain_axes_get(void)
+{
+ if (!SHC.drw_plain_axes) {
+ int axis;
+ float v1[3] = {0.0f, 0.0f, 0.0f};
+ float v2[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 6);
+
+ for (axis = 0; axis < 3; axis++) {
+ v1[axis] = 1.0f;
+ v2[axis] = -1.0f;
+
+ setAttrib(vbo, pos_id, axis * 2, v1);
+ setAttrib(vbo, pos_id, axis * 2 + 1, v2);
+
+ /* reset v1 & v2 to zero for next axis */
+ v1[axis] = v2[axis] = 0.0f;
+ }
+
+ SHC.drw_plain_axes = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_plain_axes;
+}
+
+Batch *DRW_cache_single_arrow_get(void)
+{
+ if (!SHC.drw_single_arrow) {
+ float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3], v3[3];
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ /* Square Pyramid */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 12);
+
+ v2[0] = 0.035f; v2[1] = 0.035f;
+ v3[0] = -0.035f; v3[1] = 0.035f;
+ v2[2] = v3[2] = 0.75f;
+
+ for (int sides = 0; sides < 4; sides++) {
+ if (sides % 2 == 1) {
+ v2[0] = -v2[0];
+ v3[1] = -v3[1];
+ }
+ else {
+ v2[1] = -v2[1];
+ v3[0] = -v3[0];
+ }
+
+ setAttrib(vbo, pos_id, sides * 3 + 0, v1);
+ setAttrib(vbo, pos_id, sides * 3 + 1, v2);
+ setAttrib(vbo, pos_id, sides * 3 + 2, v3);
+ }
+
+ SHC.drw_single_arrow = Batch_create(GL_TRIANGLES, vbo, NULL);
+ }
+ return SHC.drw_single_arrow;
+}
+
+Batch *DRW_cache_empty_sphere_get(void)
+{
+#define NSEGMENTS 16
+ if (!SHC.drw_empty_sphere) {
+ /* 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] = cosf(angle);
+ p[i][1] = sinf(angle);
+ }
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3);
+
+ for (int axis = 0; axis < 3; ++axis) {
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ float cv[2], v[3];
+
+ cv[0] = p[(i+j) % NSEGMENTS][0];
+ cv[1] = p[(i+j) % NSEGMENTS][1];
+
+ if (axis == 0)
+ v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f;
+ else if (axis == 1)
+ v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+ else
+ v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1];
+
+ setAttrib(vbo, pos_id, i*2 + j + (NSEGMENTS * 2 * axis), v);
+ }
+ }
+ }
+
+ SHC.drw_empty_sphere = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_empty_sphere;
+#undef NSEGMENTS
+}
+
+Batch *DRW_cache_empty_cone_get(void)
+{
+#define NSEGMENTS 8
+ if (!SHC.drw_empty_cone) {
+ /* 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] = cosf(angle);
+ p[i][1] = sinf(angle);
+ }
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
+
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float cv[2], v[3];
+ cv[0] = p[(i) % NSEGMENTS][0];
+ cv[1] = p[(i) % NSEGMENTS][1];
+
+ /* cone sides */
+ v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+ setAttrib(vbo, pos_id, i*4, v);
+ v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
+ setAttrib(vbo, pos_id, i*4 + 1, v);
+
+ /* end ring */
+ v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+ setAttrib(vbo, pos_id, i*4 + 2, v);
+ cv[0] = p[(i+1) % NSEGMENTS][0];
+ cv[1] = p[(i+1) % NSEGMENTS][1];
+ v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+ setAttrib(vbo, pos_id, i*4 + 3, v);
+ }
+
+ SHC.drw_empty_cone = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_empty_cone;
+#undef NSEGMENTS
+}
+
+Batch *DRW_cache_arrows_get(void)
+{
+ if (!SHC.drw_arrows) {
+ float v1[3] = {0.0, 0.0, 0.0};
+ float v2[3] = {0.0, 0.0, 0.0};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ /* Line */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 6 * 3);
+
+ for (int axis = 0; axis < 3; axis++) {
+ const int arrow_axis = (axis == 0) ? 1 : 0;
+
+ v2[axis] = 1.0f;
+ setAttrib(vbo, pos_id, axis * 6 + 0, v1);
+ setAttrib(vbo, pos_id, axis * 6 + 1, v2);
+
+ v1[axis] = 0.85f;
+ v1[arrow_axis] = -0.08f;
+ setAttrib(vbo, pos_id, axis * 6 + 2, v1);
+ setAttrib(vbo, pos_id, axis * 6 + 3, v2);
+
+ v1[arrow_axis] = 0.08f;
+ setAttrib(vbo, pos_id, axis * 6 + 4, v1);
+ setAttrib(vbo, pos_id, axis * 6 + 5, v2);
+
+ /* reset v1 & v2 to zero */
+ v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
+ }
+
+ SHC.drw_arrows = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_arrows;
+}
+
+/* Lamps */
+Batch *DRW_cache_lamp_get(void)
+{
+#define NSEGMENTS 8
+ if (!SHC.drw_lamp) {
+ float v[2];
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, NSEGMENTS * 2);
+
+ for (int a = 0; a < NSEGMENTS; a++) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS));
+ v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS));
+ setAttrib(vbo, pos_id, a * 2, v);
+
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
+ setAttrib(vbo, pos_id, a * 2 + 1, v);
+ }
+
+ SHC.drw_lamp = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_lamp;
+#undef NSEGMENTS
+}
+
+Batch *DRW_cache_lamp_sunrays_get(void)
+{
+ if (!SHC.drw_lamp_sunrays) {
+ float v[2], v1[2], v2[2];
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 16);
+
+ for (int a = 0; a < 8; a++) {
+ v[0] = sinf((2.0f * M_PI * a) / 8.0f);
+ v[1] = cosf((2.0f * M_PI * a) / 8.0f);
+
+ mul_v2_v2fl(v1, v, 1.2f);
+ mul_v2_v2fl(v2, v, 2.5f);
+
+ setAttrib(vbo, pos_id, a * 2, v1);
+ setAttrib(vbo, pos_id, a * 2 + 1, v2);
+ }
+
+ SHC.drw_lamp_sunrays = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_lamp_sunrays;
+}
+
+
+/* Object Center */
+Batch *DRW_cache_single_vert_get(void)
+{
+ if (!SHC.drw_single_vertice) {
+ float v1[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 1);
+
+ setAttrib(vbo, pos_id, 0, v1);
+
+ SHC.drw_single_vertice = Batch_create(GL_POINTS, vbo, NULL);
+ }
+ return SHC.drw_single_vertice;
+}
+
+/* Meshes */
+Batch *DRW_cache_wire_overlay_get(Object *ob)
+{
+ Batch *overlay_wire = NULL;
+
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+#if 1 /* new version not working */
+ overlay_wire = BKE_mesh_batch_cache_get_overlay_edges(me);
+#else
+ overlay_wire = BKE_mesh_batch_cache_get_all_edges(me);
+#endif
+ return overlay_wire;
+}
+
+Batch *DRW_cache_wire_outline_get(Object *ob)
+{
+ Batch *fancy_wire = NULL;
+
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ fancy_wire = BKE_mesh_batch_cache_get_fancy_edges(me);
+
+ return fancy_wire;
+}
+
+Batch *DRW_cache_surface_get(Object *ob)
+{
+ Batch *surface = NULL;
+
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ surface = BKE_mesh_batch_cache_get_all_triangles(me);
+
+ return surface;
+}
+
+#if 0 /* TODO */
+struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) {
+ /* TODO */
+ return NULL;
+}
+#endif \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
new file mode 100644
index 00000000000..0e467bddbfa
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_cache.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_CACHE_H__
+#define __DRAW_CACHE_H__
+
+struct Batch;
+struct Object;
+
+void DRW_shape_cache_free(void);
+
+/* Common Shapes */
+struct Batch *DRW_cache_fullscreen_quad_get(void);
+struct Batch *DRW_cache_single_vert_get(void);
+struct Batch *DRW_cache_single_line_get(void);
+
+/* Empties */
+struct Batch *DRW_cache_plain_axes_get(void);
+struct Batch *DRW_cache_single_arrow_get(void);
+struct Batch *DRW_cache_cube_get(void);
+struct Batch *DRW_cache_circle_get(void);
+struct Batch *DRW_cache_empty_sphere_get(void);
+struct Batch *DRW_cache_empty_cone_get(void);
+struct Batch *DRW_cache_arrows_get(void);
+
+/* Lamps */
+struct Batch *DRW_cache_lamp_get(void);
+struct Batch *DRW_cache_lamp_sunrays_get(void);
+
+/* Meshes */
+struct Batch *DRW_cache_wire_overlay_get(struct Object *ob);
+struct Batch *DRW_cache_wire_outline_get(struct Object *ob);
+struct Batch *DRW_cache_surface_get(struct Object *ob);
+
+#endif /* __DRAW_CACHE_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
new file mode 100644
index 00000000000..970bd2f6dee
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager.c
@@ -0,0 +1,1272 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/draw_manager.c
+ * \ingroup draw
+ */
+
+#include <stdio.h>
+
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+
+#include "BIF_glutil.h"
+
+#include "BKE_global.h"
+
+#include "BLT_translation.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_view3d_types.h"
+
+#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+
+#include "RE_engine.h"
+
+#include "UI_resources.h"
+
+#include "clay.h"
+
+#define MAX_ATTRIB_NAME 32
+
+extern char datatoc_gpu_shader_2D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_basic_vert_glsl[];
+
+/* Structures */
+typedef enum {
+ DRW_UNIFORM_BOOL,
+ DRW_UNIFORM_INT,
+ DRW_UNIFORM_FLOAT,
+ DRW_UNIFORM_TEXTURE,
+ DRW_UNIFORM_BUFFER,
+ DRW_UNIFORM_MAT3,
+ DRW_UNIFORM_MAT4,
+ DRW_UNIFORM_BLOCK
+} DRWUniformType;
+
+typedef enum {
+ DRW_ATTRIB_INT,
+ DRW_ATTRIB_FLOAT,
+} DRWAttribType;
+
+typedef struct DRWUniform {
+ struct DRWUniform *next, *prev;
+ DRWUniformType type;
+ int location;
+ int length;
+ int arraysize;
+ int bindloc;
+ const void *value;
+} DRWUniform;
+
+typedef struct DRWAttrib {
+ struct DRWAttrib *next, *prev;
+ char name[MAX_ATTRIB_NAME];
+ int location;
+ int format_id;
+ int size; /* number of component */
+ int type;
+} DRWAttrib;
+
+struct DRWInterface {
+ ListBase uniforms; /* DRWUniform */
+ ListBase attribs; /* DRWAttrib */
+ int attribs_count;
+ int attribs_stride;
+ int attribs_size[16];
+ int attribs_loc[16];
+ /* matrices locations */
+ int modelview;
+ int projection;
+ int modelviewprojection;
+ int viewprojection;
+ int normal;
+ int eye;
+ /* Dynamic batch */
+ GLuint instance_vbo;
+ int instance_count;
+ VertexFormat vbo_format;
+};
+
+struct DRWPass {
+ ListBase shgroups; /* DRWShadingGroup */
+ DRWState state;
+ float state_param; /* Line / Point width */
+};
+
+typedef struct DRWCall {
+ struct DRWCall *next, *prev;
+ Batch *geometry;
+ float (*obmat)[4];
+} DRWCall;
+
+typedef struct DRWDynamicCall {
+ struct DRWDynamicCall *next, *prev;
+ const void *data[];
+} DRWDynamicCall;
+
+struct DRWShadingGroup {
+ struct DRWShadingGroup *next, *prev;
+
+ struct GPUShader *shader; /* Shader to bind */
+ struct DRWInterface *interface; /* Uniforms pointers */
+ ListBase calls; /* DRWCall or DRWDynamicCall depending of type*/
+ int state; /* State changes for this batch only */
+ int type;
+
+ Batch *instance_geom; /* Geometry to instance */
+ Batch *batch_geom; /* Result of call batching */
+};
+
+/* Used by DRWShadingGroup.type */
+enum {
+ DRW_SHG_NORMAL,
+ DRW_SHG_POINT_BATCH,
+ DRW_SHG_LINE_BATCH,
+ DRW_SHG_INSTANCE,
+};
+
+/* Render State */
+static struct DRWGlobalState{
+ GPUShader *shader;
+ struct GPUFrameBuffer *default_framebuffer;
+ FramebufferList *current_fbl;
+ TextureList *current_txl;
+ PassList *current_psl;
+ ListBase bound_texs;
+ int tex_bind_id;
+ float size[2];
+ float screenvecs[2][3];
+ float pixsize;
+ /* Current rendering context set by DRW_viewport_init */
+ const struct bContext *context;
+} DST = {NULL};
+
+/* ***************************************** TEXTURES ******************************************/
+static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *data_type, int *channels)
+{
+ switch (format) {
+ case DRW_TEX_RGBA_8: *data_type = GPU_RGBA8; break;
+ case DRW_TEX_RGBA_16: *data_type = GPU_RGBA16F; break;
+ case DRW_TEX_RG_16: *data_type = GPU_RG16F; break;
+ case DRW_TEX_RG_32: *data_type = GPU_RG32F; break;
+ case DRW_TEX_R_8: *data_type = GPU_R8; break;
+#if 0
+ case DRW_TEX_RGBA_32: *data_type = GPU_RGBA32F; break;
+ case DRW_TEX_RGB_8: *data_type = GPU_RGB8; break;
+ case DRW_TEX_RGB_16: *data_type = GPU_RGB16F; break;
+ case DRW_TEX_RGB_32: *data_type = GPU_RGB32F; break;
+ case DRW_TEX_RG_8: *data_type = GPU_RG8; break;
+ case DRW_TEX_R_16: *data_type = GPU_R16F; break;
+ case DRW_TEX_R_32: *data_type = GPU_R32F; break;
+#endif
+ case DRW_TEX_DEPTH_16: *data_type = GPU_DEPTH_COMPONENT16; break;
+ case DRW_TEX_DEPTH_24: *data_type = GPU_DEPTH_COMPONENT24; break;
+ case DRW_TEX_DEPTH_32: *data_type = GPU_DEPTH_COMPONENT32F; break;
+ default :
+ /* file type not supported you must uncomment it from above */
+ BLI_assert(false);
+ break;
+ }
+
+ switch (format) {
+ case DRW_TEX_RGBA_8:
+ case DRW_TEX_RGBA_16:
+ case DRW_TEX_RGBA_32:
+ *channels = 4;
+ break;
+ case DRW_TEX_RGB_8:
+ case DRW_TEX_RGB_16:
+ case DRW_TEX_RGB_32:
+ *channels = 3;
+ break;
+ case DRW_TEX_RG_8:
+ case DRW_TEX_RG_16:
+ case DRW_TEX_RG_32:
+ *channels = 2;
+ break;
+ default:
+ *channels = 1;
+ break;
+ }
+}
+
+static void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
+{
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
+ GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP);
+ GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
+ GPU_texture_unbind(tex);
+}
+
+GPUTexture *DRW_texture_create_1D(int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, &data_type, &channels);
+ tex = GPU_texture_create_1D_custom(w, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_create_2D(int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+ GPUTextureFormat data_type;
+ int channels;
+
+ drw_texture_get_format(format, &data_type, &channels);
+ tex = GPU_texture_create_2D_custom(w, h, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+/* TODO make use of format */
+GPUTexture *DRW_texture_create_2D_array(int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex;
+
+ tex = GPU_texture_create_2D_array(w, h, d, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+void DRW_texture_free(GPUTexture *tex)
+{
+ GPU_texture_free(tex);
+}
+
+
+/* ************************************ UNIFORM BUFFER OBJECT **********************************/
+
+GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data)
+{
+ return GPU_uniformbuffer_create(size, data, NULL);
+}
+
+void DRW_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+{
+ GPU_uniformbuffer_update(ubo, data);
+}
+
+void DRW_uniformbuffer_free(GPUUniformBuffer *ubo)
+{
+ GPU_uniformbuffer_free(ubo);
+}
+
+/* ****************************************** SHADERS ******************************************/
+
+GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines)
+{
+ return GPU_shader_create(vert, frag, geom, NULL, defines, 0, 0, 0);
+}
+
+GPUShader *DRW_shader_create_2D(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
+}
+
+GPUShader *DRW_shader_create_3D(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
+}
+
+GPUShader *DRW_shader_create_3D_depth_only(void)
+{
+ return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
+}
+
+void DRW_shader_free(GPUShader *shader)
+{
+ GPU_shader_free(shader);
+}
+
+/* ***************************************** INTERFACE ******************************************/
+
+static DRWInterface *DRW_interface_create(GPUShader *shader)
+{
+ DRWInterface *interface = MEM_mallocN(sizeof(DRWInterface), "DRWInterface");
+
+ interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix");
+ interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix");
+ interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix");
+ interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix");
+ interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix");
+ interface->eye = GPU_shader_get_uniform(shader, "eye");
+ interface->instance_count = 0;
+ interface->attribs_count = 0;
+ interface->attribs_stride = 0;
+ interface->instance_vbo = 0;
+
+ memset(&interface->vbo_format, 0, sizeof(VertexFormat));
+
+ BLI_listbase_clear(&interface->uniforms);
+ BLI_listbase_clear(&interface->attribs);
+
+ return interface;
+}
+
+static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
+ DRWUniformType type, const void *value, int length, int arraysize, int bindloc)
+{
+ DRWUniform *uni = MEM_mallocN(sizeof(DRWUniform), "DRWUniform");
+
+ if (type == DRW_UNIFORM_BLOCK) {
+ uni->location = GPU_shader_get_uniform_block(shgroup->shader, name);
+ }
+ else {
+ uni->location = GPU_shader_get_uniform(shgroup->shader, name);
+ }
+
+ uni->type = type;
+ uni->value = value;
+ uni->length = length;
+ uni->arraysize = arraysize;
+ uni->bindloc = bindloc; /* for textures */
+
+ if (uni->location == -1) {
+ if (G.debug & G_DEBUG)
+ fprintf(stderr, "Uniform '%s' not found!\n", name);
+
+ MEM_freeN(uni);
+ return;
+ }
+
+ BLI_addtail(&shgroup->interface->uniforms, uni);
+}
+
+static void DRW_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType type, int size)
+{
+ DRWAttrib *attrib = MEM_mallocN(sizeof(DRWAttrib), "DRWAttrib");
+ GLuint program = GPU_shader_get_program(shgroup->shader);
+
+ attrib->location = glGetAttribLocation(program, name);
+ attrib->type = type;
+ attrib->size = size;
+
+ if (attrib->location == -1) {
+ if (G.debug & G_DEBUG)
+ fprintf(stderr, "Attribute '%s' not found!\n", name);
+
+ MEM_freeN(attrib);
+ return;
+ }
+
+ BLI_assert(BLI_strnlen(name, 32) < 32);
+ BLI_strncpy(attrib->name, name, 32);
+
+ shgroup->interface->attribs_count += 1;
+
+ BLI_addtail(&shgroup->interface->attribs, attrib);
+}
+
+void DRW_get_dfdy_factors(float dfdyfac[2])
+{
+ GPU_get_dfdy_factors(dfdyfac);
+}
+
+/* ***************************************** SHADING GROUP ******************************************/
+
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
+{
+ DRWShadingGroup *shgroup = MEM_mallocN(sizeof(DRWShadingGroup), "DRWShadingGroup");
+
+ shgroup->type = DRW_SHG_NORMAL;
+ shgroup->shader = shader;
+ shgroup->interface = DRW_interface_create(shader);
+ shgroup->state = 0;
+ shgroup->batch_geom = NULL;
+ shgroup->instance_geom = NULL;
+
+ BLI_addtail(&pass->shgroups, shgroup);
+ BLI_listbase_clear(&shgroup->calls);
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, Batch *geom)
+{
+ DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
+
+ shgroup->type = DRW_SHG_INSTANCE;
+ shgroup->instance_geom = geom;
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass)
+{
+ DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
+
+ shgroup->type = DRW_SHG_POINT_BATCH;
+ DRW_shgroup_attrib_float(shgroup, "pos", 3);
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass)
+{
+ DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
+
+ shgroup->type = DRW_SHG_LINE_BATCH;
+ DRW_shgroup_attrib_float(shgroup, "pos", 3);
+
+ return shgroup;
+}
+
+void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
+{
+ BLI_freelistN(&shgroup->calls);
+ BLI_freelistN(&shgroup->interface->uniforms);
+ BLI_freelistN(&shgroup->interface->attribs);
+ /* TODO free instance vbo */
+ MEM_freeN(shgroup->interface);
+
+ if (shgroup->batch_geom) {
+ Batch_discard_all(shgroup->batch_geom);
+ }
+}
+
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[4])
+{
+ if (geom) {
+ DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall");
+
+ call->obmat = obmat;
+ call->geometry = geom;
+
+ BLI_addtail(&shgroup->calls, call);
+ }
+}
+
+void DRW_shgroup_dynamic_call_add(DRWShadingGroup *shgroup, ...)
+{
+ va_list params;
+ int i;
+ DRWInterface *interface = shgroup->interface;
+ int size = sizeof(ListBase) + sizeof(void *) * interface->attribs_count;
+
+ DRWDynamicCall *call = MEM_callocN(size, "DRWDynamicCall");
+
+ va_start(params, shgroup);
+ for (i = 0; i < interface->attribs_count; ++i) {
+ call->data[i] = va_arg(params, void *);
+ }
+ va_end(params);
+
+ interface->instance_count += 1;
+
+ BLI_addtail(&shgroup->calls, call);
+}
+
+/* Make sure you know what you do when using this,
+ * State is not revert back at the end of the shgroup */
+void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state)
+{
+ shgroup->state = state;
+}
+
+void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size)
+{
+ DRW_interface_attrib(shgroup, name, DRW_ATTRIB_FLOAT, size);
+}
+
+void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex, int loc)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 0, loc);
+}
+
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo, int loc)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 0, loc);
+}
+
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc)
+{
+ /* we abuse the lenght attrib to store the buffer index */
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, NULL, value, 0, loc);
+}
+
+void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 1, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 2, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 3, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 2, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 3, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_MAT3, value, 9, 1, 0);
+}
+
+void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_MAT4, value, 16, 1, 0);
+}
+
+/* Creates a VBO containing OGL primitives for all DRWDynamicCall */
+static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
+{
+ DRWInterface *interface = shgroup->interface;
+ int nbr = interface->instance_count;
+
+ GLenum type = (shgroup->type == DRW_SHG_POINT_BATCH) ? GL_POINTS : GL_LINES;
+
+ if (nbr == 0)
+ return;
+
+ /* Upload Data */
+ if (interface->vbo_format.attrib_ct == 0) {
+ for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next) {
+ BLI_assert(attrib->size <= 4); /* matrices have no place here for now */
+ if (attrib->type == DRW_ATTRIB_FLOAT) {
+ attrib->format_id = add_attrib(&interface->vbo_format, attrib->name, GL_FLOAT, attrib->size, KEEP_FLOAT);
+ }
+ else if (attrib->type == DRW_ATTRIB_INT) {
+ attrib->format_id = add_attrib(&interface->vbo_format, attrib->name, GL_BYTE, attrib->size, KEEP_INT);
+ }
+ else {
+ BLI_assert(false);
+ }
+ }
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&interface->vbo_format);
+ VertexBuffer_allocate_data(vbo, nbr);
+
+ int j = 0;
+ for (DRWDynamicCall *call = shgroup->calls.first; call; call = call->next, j++) {
+ int i = 0;
+ for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next, i++) {
+ setAttrib(vbo, attrib->format_id, j, call->data[i]);
+ }
+ }
+
+ /* TODO make the batch dynamic instead of freeing it every times */
+ if (shgroup->batch_geom)
+ Batch_discard_all(shgroup->batch_geom);
+
+ shgroup->batch_geom = Batch_create(type, vbo, NULL);
+}
+
+static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
+{
+ int i = 0;
+ int offset = 0;
+ DRWInterface *interface = shgroup->interface;
+ int vert_nbr = interface->instance_count;
+ int buffer_size = 0;
+
+ if (vert_nbr == 0) {
+ if (interface->instance_vbo) {
+ glDeleteBuffers(1, &interface->instance_vbo);
+ interface->instance_vbo = 0;
+ }
+ return;
+ }
+
+ /* only once */
+ if (interface->attribs_stride == 0) {
+ for (DRWAttrib *attrib = interface->attribs.first; attrib; attrib = attrib->next, i++) {
+ BLI_assert(attrib->type == DRW_ATTRIB_FLOAT); /* Only float for now */
+ interface->attribs_stride += attrib->size;
+ interface->attribs_size[i] = attrib->size;
+ interface->attribs_loc[i] = attrib->location;
+ }
+ }
+
+ /* Gather Data */
+ buffer_size = sizeof(float) * interface->attribs_stride * vert_nbr;
+ float *data = MEM_mallocN(buffer_size, "Instance VBO data");
+
+ for (DRWDynamicCall *call = shgroup->calls.first; call; call = call->next) {
+ for (int j = 0; j < interface->attribs_count; ++j) {
+ memcpy(data + offset, call->data[j], sizeof(float) * interface->attribs_size[j]);
+ offset += interface->attribs_size[j];
+ }
+ }
+
+ /* TODO poke mike to add this to gawain */
+ if (interface->instance_vbo) {
+ glDeleteBuffers(1, &interface->instance_vbo);
+ interface->instance_vbo = 0;
+ }
+
+ glGenBuffers(1, &interface->instance_vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, interface->instance_vbo);
+ glBufferData(GL_ARRAY_BUFFER, buffer_size, data, GL_STATIC_DRAW);
+
+ MEM_freeN(data);
+}
+
+static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
+{
+#ifdef WITH_VIEWPORT_CACHE_TEST
+ if (shgroup->interface->instance_vbo || shgroup->batch_geom) return;
+#endif
+ if (shgroup->type == DRW_SHG_INSTANCE) {
+ shgroup_dynamic_instance(shgroup);
+ }
+ else {
+ shgroup_dynamic_batch(shgroup);
+ }
+}
+
+/* ***************************************** PASSES ******************************************/
+
+DRWPass *DRW_pass_create(const char *name, DRWState state)
+{
+ DRWPass *pass = MEM_callocN(sizeof(DRWPass), name);
+ pass->state = state;
+
+ BLI_listbase_clear(&pass->shgroups);
+
+ return pass;
+}
+
+void DRW_pass_free(DRWPass *pass)
+{
+ for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
+ DRW_shgroup_free(shgroup);
+ }
+ BLI_freelistN(&pass->shgroups);
+}
+
+/* ****************************************** DRAW ******************************************/
+
+void DRW_draw_background(void)
+{
+ /* Just to make sure */
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ /* Gradient background Color */
+ gpuMatrixBegin3D(); /* TODO: finish 2D API */
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+ unsigned char col_hi[3], col_lo[3];
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
+ UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
+
+ immBegin(GL_QUADS, 4);
+ immAttrib3ubv(color, col_lo);
+ immVertex2f(pos, -1.0f, -1.0f);
+ immVertex2f(pos, 1.0f, -1.0f);
+
+ immAttrib3ubv(color, col_hi);
+ immVertex2f(pos, 1.0f, 1.0f);
+ immVertex2f(pos, -1.0f, 1.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuMatrixEnd();
+ }
+ else {
+ /* Solid background Color */
+ UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+}
+#ifdef WITH_CLAY_ENGINE
+/* Only alter the state (does not reset it like set_state() ) */
+static void shgroup_set_state(DRWShadingGroup *shgroup)
+{
+ if (shgroup->state) {
+ /* Blend */
+ if (shgroup->state & DRW_STATE_BLEND) {
+ glEnable(GL_BLEND);
+ }
+
+ /* Wire width */
+ if (shgroup->state & DRW_STATE_WIRE) {
+ glLineWidth(1.0f);
+ }
+ else if (shgroup->state & DRW_STATE_WIRE_LARGE) {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ }
+
+ /* Line Stipple */
+ if (shgroup->state & DRW_STATE_STIPPLE_2) {
+ setlinestyle(2);
+ }
+ else if (shgroup->state & DRW_STATE_STIPPLE_3) {
+ setlinestyle(3);
+ }
+ else if (shgroup->state & DRW_STATE_STIPPLE_4) {
+ setlinestyle(4);
+ }
+
+ if (shgroup->state & DRW_STATE_POINT) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ }
+}
+
+typedef struct DRWBoundTexture {
+ struct DRWBoundTexture *next, *prev;
+ GPUTexture *tex;
+} DRWBoundTexture;
+
+static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*obmat)[4])
+{
+ RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+ DRWInterface *interface = shgroup->interface;
+
+ float mvp[4][4], mv[4][4], n[3][3];
+ float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
+
+ bool do_mvp = (interface->modelviewprojection != -1);
+ bool do_mv = (interface->modelview != -1);
+ bool do_n = (interface->normal != -1);
+ bool do_eye = (interface->eye != -1);
+
+ if (do_mvp) {
+ mul_m4_m4m4(mvp, rv3d->persmat, obmat);
+ }
+ if (do_mv || do_n || do_eye) {
+ mul_m4_m4m4(mv, rv3d->viewmat, obmat);
+ }
+ if (do_n || do_eye) {
+ copy_m3_m4(n, mv);
+ invert_m3(n);
+ transpose_m3(n);
+ }
+ if (do_eye) {
+ /* Used by orthographic wires */
+ float tmp[3][3];
+ invert_m3_m3(tmp, n);
+ /* set eye vector, transformed to object coords */
+ mul_m3_v3(tmp, eye);
+ }
+
+ /* Should be really simple */
+ /* step 1 : bind object dependent matrices */
+ if (interface->modelviewprojection != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp);
+ }
+ if (interface->viewprojection != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->viewprojection, 16, 1, (float *)rv3d->persmat);
+ }
+ if (interface->projection != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)rv3d->winmat);
+ }
+ if (interface->modelview != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv);
+ }
+ if (interface->normal != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->normal, 9, 1, (float *)n);
+ }
+ if (interface->eye != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
+ }
+
+ /* step 2 : bind vertex array & draw */
+ Batch_set_program(geom, GPU_shader_get_program(shgroup->shader));
+ if (interface->instance_vbo) {
+ Batch_draw_stupid_instanced(geom, interface->instance_vbo, interface->instance_count, interface->attribs_count,
+ interface->attribs_stride, interface->attribs_size, interface->attribs_loc);
+ }
+ else {
+ Batch_draw_stupid(geom);
+ }
+}
+
+static void draw_shgroup(DRWShadingGroup *shgroup)
+{
+ BLI_assert(shgroup->shader);
+ BLI_assert(shgroup->interface);
+
+ DRWInterface *interface = shgroup->interface;
+
+ if (DST.shader != shgroup->shader) {
+ if (DST.shader) GPU_shader_unbind();
+ GPU_shader_bind(shgroup->shader);
+ DST.shader = shgroup->shader;
+ }
+
+ if (shgroup->type != DRW_SHG_NORMAL) {
+ shgroup_dynamic_batch_from_calls(shgroup);
+ }
+
+ shgroup_set_state(shgroup);
+
+ /* Binding Uniform */
+ /* Don't check anything, Interface should already contain the least uniform as possible */
+ for (DRWUniform *uni = interface->uniforms.first; uni; uni = uni->next) {
+ DRWBoundTexture *bound_tex;
+
+ switch (uni->type) {
+ case DRW_UNIFORM_BOOL:
+ case DRW_UNIFORM_INT:
+ GPU_shader_uniform_vector_int(shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->value);
+ break;
+ case DRW_UNIFORM_FLOAT:
+ case DRW_UNIFORM_MAT3:
+ case DRW_UNIFORM_MAT4:
+ GPU_shader_uniform_vector(shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->value);
+ break;
+ case DRW_UNIFORM_TEXTURE:
+ GPU_texture_bind((GPUTexture *)uni->value, uni->bindloc);
+
+ bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
+ bound_tex->tex = (GPUTexture *)uni->value;
+ BLI_addtail(&DST.bound_texs, bound_tex);
+
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, (GPUTexture *)uni->value);
+ break;
+ case DRW_UNIFORM_BUFFER:
+ /* restore index from lenght we abused */
+ GPU_texture_bind(DST.current_txl->textures[uni->length], uni->bindloc);
+ GPU_texture_compare_mode(DST.current_txl->textures[uni->length], false);
+ GPU_texture_filter_mode(DST.current_txl->textures[uni->length], false);
+
+ bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
+ bound_tex->tex = DST.current_txl->textures[uni->length];
+ BLI_addtail(&DST.bound_texs, bound_tex);
+
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, DST.current_txl->textures[uni->length]);
+ break;
+ case DRW_UNIFORM_BLOCK:
+ GPU_uniformbuffer_bind((GPUUniformBuffer *)uni->value, uni->bindloc);
+ GPU_shader_uniform_buffer(shgroup->shader, uni->location, (GPUUniformBuffer *)uni->value);
+ break;
+ }
+ }
+
+ /* Rendering Calls */
+ if (shgroup->type != DRW_SHG_NORMAL) {
+ /* Replacing multiple calls with only one */
+ float obmat[4][4];
+ unit_m4(obmat);
+
+ if (shgroup->type == DRW_SHG_INSTANCE && interface->instance_count > 0) {
+ draw_geometry(shgroup, shgroup->instance_geom, obmat);
+ }
+ else {
+ /* Some dynamic batch can have no geom (no call to aggregate) */
+ if (shgroup->batch_geom) {
+ draw_geometry(shgroup, shgroup->batch_geom, obmat);
+ }
+ }
+ }
+ else {
+ for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
+ draw_geometry(shgroup, call->geometry, call->obmat);
+ }
+ }
+}
+
+static void set_state(short flag)
+{
+ /* TODO Keep track of the state and only revert what is needed */
+
+ /* Depth Write */
+ if (flag & DRW_STATE_WRITE_DEPTH)
+ glDepthMask(GL_TRUE);
+ else
+ glDepthMask(GL_FALSE);
+
+ /* Color Write */
+ if (flag & DRW_STATE_WRITE_COLOR)
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ else
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* Backface Culling */
+ if (flag & DRW_STATE_CULL_BACK ||
+ flag & DRW_STATE_CULL_FRONT) {
+
+ glEnable(GL_CULL_FACE);
+
+ if (flag & DRW_STATE_CULL_BACK)
+ glCullFace(GL_BACK);
+ else if (flag & DRW_STATE_CULL_FRONT)
+ glCullFace(GL_FRONT);
+ }
+ else {
+ glDisable(GL_CULL_FACE);
+ }
+
+ /* Depht Test */
+ if (flag & DRW_STATE_DEPTH_LESS ||
+ flag & DRW_STATE_DEPTH_EQUAL) {
+
+ glEnable(GL_DEPTH_TEST);
+
+ if (flag & DRW_STATE_DEPTH_LESS)
+ glDepthFunc(GL_LEQUAL);
+ else if (flag & DRW_STATE_DEPTH_EQUAL)
+ glDepthFunc(GL_EQUAL);
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ /* Wire Width */
+ if (flag & DRW_STATE_WIRE) {
+ glLineWidth(1.0f);
+ }
+ else if (flag & DRW_STATE_WIRE_LARGE) {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ }
+
+ /* Points Size */
+ if (flag & DRW_STATE_POINT) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ else {
+ GPU_disable_program_point_size();
+ }
+
+ /* Blending (all buffer) */
+ if (flag & DRW_STATE_BLEND) {
+ glEnable(GL_BLEND);
+ }
+ else {
+ glDisable(GL_BLEND);
+ }
+
+ /* Line Stipple */
+ if (flag & DRW_STATE_STIPPLE_2) {
+ setlinestyle(2);
+ }
+ else if (flag & DRW_STATE_STIPPLE_3) {
+ setlinestyle(3);
+ }
+ else if (flag & DRW_STATE_STIPPLE_4) {
+ setlinestyle(4);
+ }
+ else {
+ setlinestyle(0);
+ }
+}
+
+void DRW_draw_pass(DRWPass *pass)
+{
+ /* Start fresh */
+ DST.shader = NULL;
+ DST.tex_bind_id = 0;
+
+ set_state(pass->state);
+ BLI_listbase_clear(&DST.bound_texs);
+
+ for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
+ draw_shgroup(shgroup);
+ }
+
+ /* Clear Bound textures */
+ for (DRWBoundTexture *bound_tex = DST.bound_texs.first; bound_tex; bound_tex = bound_tex->next) {
+ GPU_texture_unbind(bound_tex->tex);
+ }
+ DST.tex_bind_id = 0;
+ BLI_freelistN(&DST.bound_texs);
+
+ if (DST.shader) {
+ GPU_shader_unbind();
+ DST.shader = NULL;
+ }
+}
+
+/* Reset state to not interfer with other UI drawcall */
+void DRW_state_reset(void)
+{
+ DRWState state = 0;
+ state |= DRW_STATE_WRITE_DEPTH;
+ state |= DRW_STATE_WRITE_COLOR;
+ state |= DRW_STATE_DEPTH_LESS;
+ set_state(state);
+}
+#endif
+/* ****************************************** Settings ******************************************/
+void *DRW_material_settings_get(Material *ma, const char *engine_name)
+{
+ MaterialEngineSettings *ms = NULL;
+
+ ms = BLI_findstring(&ma->engines_settings, engine_name, offsetof(MaterialEngineSettings, name));
+
+#ifdef WITH_CLAY_ENGINE
+ /* If the settings does not exists yet, create it */
+ if (ms == NULL) {
+ ms = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
+
+ BLI_strncpy(ms->name, engine_name, 32);
+
+ /* TODO make render_settings_create a polymorphic function */
+ if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
+ ms->data = CLAY_material_settings_create();
+ }
+ else {
+ /* No engine matched */
+ BLI_assert(false);
+ }
+
+ BLI_addtail(&ma->engines_settings, ms);
+ }
+#else
+ return NULL;
+#endif
+
+ return ms->data;
+}
+
+/* If scene is NULL, use context scene */
+void *DRW_render_settings_get(Scene *scene, const char *engine_name)
+{
+ RenderEngineSettings *rs = NULL;
+
+ if (scene == NULL)
+ scene = CTX_data_scene(DST.context);
+
+ rs = BLI_findstring(&scene->engines_settings, engine_name, offsetof(RenderEngineSettings, name));
+
+#ifdef WITH_CLAY_ENGINE
+ /* If the settings does not exists yet, create it */
+ if (rs == NULL) {
+ rs = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
+
+ BLI_strncpy(rs->name, engine_name, 32);
+
+ /* TODO make render_settings_create a polymorphic function */
+ if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
+ rs->data = CLAY_render_settings_create();
+ }
+ else {
+ /* No engine matched */
+ BLI_assert(false);
+ }
+
+ BLI_addtail(&scene->engines_settings, rs);
+ }
+#else
+ return NULL;
+#endif
+
+ return rs->data;
+}
+/* ****************************************** Framebuffers ******************************************/
+
+void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX],
+ int texnbr)
+{
+ if (!*fb) {
+ int color_attachment = -1;
+ *fb = GPU_framebuffer_create();
+
+ for (int i = 0; i < texnbr; ++i)
+ {
+ DRWFboTexture fbotex = textures[i];
+
+ if (!*fbotex.tex) {
+ /* TODO refine to opengl formats */
+ if (fbotex.format == DRW_BUF_DEPTH_16 ||
+ fbotex.format == DRW_BUF_DEPTH_24) {
+ *fbotex.tex = GPU_texture_create_depth(width, height, NULL);
+ GPU_texture_compare_mode(*fbotex.tex, false);
+ GPU_texture_filter_mode(*fbotex.tex, false);
+ }
+ else {
+ *fbotex.tex = GPU_texture_create_2D(width, height, NULL, NULL);
+ ++color_attachment;
+ }
+ }
+
+ GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment);
+ }
+
+ if (!GPU_framebuffer_check_valid(*fb, NULL)) {
+ printf("Error invalid framebuffer\n");
+ }
+
+ GPU_framebuffer_bind(DST.default_framebuffer);
+ }
+}
+
+void DRW_framebuffer_bind(struct GPUFrameBuffer *fb)
+{
+ GPU_framebuffer_bind(fb);
+}
+
+void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot)
+{
+ GPU_framebuffer_texture_attach(fb, tex, slot);
+}
+
+void DRW_framebuffer_texture_detach(GPUTexture *tex)
+{
+ GPU_framebuffer_texture_detach(tex);
+}
+
+/* ****************************************** Viewport ******************************************/
+
+float *DRW_viewport_size_get(void)
+{
+ return &DST.size[0];
+}
+
+float *DRW_viewport_screenvecs_get(void)
+{
+ return &DST.screenvecs[0][0];
+}
+
+float *DRW_viewport_pixelsize_get(void)
+{
+ return &DST.pixsize;
+}
+
+void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes, void **storage)
+{
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ GPUViewport *viewport = rv3d->viewport;
+
+ GPU_viewport_get_engine_data(viewport, buffers, textures, passes, storage);
+
+ /* Refresh DST.size */
+ DefaultTextureList *txl = (DefaultTextureList *)*textures;
+ DST.size[0] = (float)GPU_texture_width(txl->color);
+ DST.size[1] = (float)GPU_texture_height(txl->color);
+
+ DefaultFramebufferList *fbl = (DefaultFramebufferList *)*buffers;
+ DST.default_framebuffer = fbl->default_fb;
+
+ DST.current_txl = (TextureList *)*textures;
+ DST.current_fbl = (FramebufferList *)*buffers;
+ DST.current_psl = (PassList *)*passes;
+
+ /* Refresh DST.screenvecs */
+ copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
+ copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
+ normalize_v3(DST.screenvecs[0]);
+ normalize_v3(DST.screenvecs[1]);
+
+ /* Refresh DST.pixelsize */
+ DST.pixsize = rv3d->pixsize;
+
+ /* Save context for all later needs */
+ DST.context = C;
+}
+
+void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
+{
+ RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+
+ if (type == DRW_MAT_PERS)
+ copy_m4_m4(mat, rv3d->persmat);
+ else if (type == DRW_MAT_WIEW)
+ copy_m4_m4(mat, rv3d->viewmat);
+ else if (type == DRW_MAT_WIN)
+ copy_m4_m4(mat, rv3d->winmat);
+}
+
+bool DRW_viewport_is_persp_get(void)
+{
+ RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+ return rv3d->is_persp;
+}
+
+bool DRW_viewport_cache_is_dirty(void)
+{
+ /* TODO Use a dirty flag */
+ return (DST.current_psl->passes[0] == NULL);
+}
+
+/* ****************************************** INIT ******************************************/
+
+void DRW_engines_init(void)
+{
+#ifdef WITH_CLAY_ENGINE
+ RE_engines_register(NULL, &viewport_clay_type);
+#endif
+}
+
+void DRW_engines_free(void)
+{
+#ifdef WITH_CLAY_ENGINE
+ clay_engine_free();
+
+ DRW_shape_cache_free();
+
+ BLI_remlink(&R_engines, &viewport_clay_type);
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c
new file mode 100644
index 00000000000..0298db1a5ca
--- /dev/null
+++ b/source/blender/draw/intern/draw_mode_pass.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/draw_mode_pass.c
+ * \ingroup draw
+ */
+
+#include "DNA_userdef_types.h"
+
+#include "GPU_shader.h"
+
+#include "UI_resources.h"
+
+#include "BKE_global.h"
+
+#include "draw_mode_pass.h"
+
+/* ************************** OBJECT MODE ******************************* */
+
+/* Store list of shading group for easy access*/
+
+/* Empties */
+static DRWShadingGroup *plain_axes;
+static DRWShadingGroup *cube;
+static DRWShadingGroup *circle;
+static DRWShadingGroup *sphere;
+static DRWShadingGroup *cone;
+static DRWShadingGroup *single_arrow;
+static DRWShadingGroup *single_arrow_line;
+static DRWShadingGroup *arrows;
+
+/* Lamps */
+static DRWShadingGroup *lamp_center;
+static DRWShadingGroup *lamp_center_group;
+static DRWShadingGroup *lamp_groundpoint;
+static DRWShadingGroup *lamp_groundline;
+static DRWShadingGroup *lamp_circle;
+static DRWShadingGroup *lamp_circle_shadow;
+static DRWShadingGroup *lamp_sunrays;
+
+/* Helpers */
+static DRWShadingGroup *relationship_lines;
+
+/* Objects Centers */
+static DRWShadingGroup *center_active;
+static DRWShadingGroup *center_selected;
+static DRWShadingGroup *center_deselected;
+
+/* Colors & Constant */
+static float colorWire[4], colorWireEdit[4];
+static float colorActive[4], colorSelect[4], colorTransform[4], colorGroup[4], colorGroupActive[4];
+static float colorEmpty[4], colorLamp[4], colorCamera[4], colorSpeaker[4];
+static float lampCenterSize, lampCircleRad, lampCircleShadowRad, colorLampNoAlpha[4];
+
+static DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+
+ return grp;
+}
+
+static DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+
+ DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+ DRW_shgroup_uniform_float(grp, "size", size, 1);
+ DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+
+ return grp;
+}
+
+static DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE);
+
+ DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+
+ return grp;
+}
+
+static DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT);
+
+ DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+ DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+
+ return grp;
+}
+
+static DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch *geom, float *size)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR
+);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "world_pos", 3);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_uniform_float(grp, "size", size, 1);
+ DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
+ DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
+ DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
+
+ return grp;
+}
+
+static DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "size", 1);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+
+ return grp;
+}
+
+/* This Function setup the passes needed for the mode rendering.
+ * The passes are populated by the rendering engine using the DRW_shgroup_* functions. */
+void DRW_pass_setup_common(DRWPass **wire_overlay, DRWPass **wire_outline, DRWPass **non_meshes, DRWPass **ob_center)
+{
+ UI_GetThemeColor4fv(TH_WIRE, colorWire);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, colorWireEdit);
+ UI_GetThemeColor4fv(TH_ACTIVE, colorActive);
+ UI_GetThemeColor4fv(TH_SELECT, colorSelect);
+ UI_GetThemeColor4fv(TH_TRANSFORM, colorTransform);
+ UI_GetThemeColor4fv(TH_GROUP_ACTIVE, colorGroupActive);
+ UI_GetThemeColor4fv(TH_GROUP, colorGroup);
+ UI_GetThemeColor4fv(TH_LAMP, colorLamp);
+ UI_GetThemeColor4fv(TH_LAMP, colorLampNoAlpha);
+ UI_GetThemeColor4fv(TH_SPEAKER, colorSpeaker);
+ UI_GetThemeColor4fv(TH_CAMERA, colorCamera);
+ UI_GetThemeColor4fv(TH_EMPTY, colorEmpty);
+
+ colorLampNoAlpha[3] = 1.0f;
+
+ if (wire_overlay) {
+ /* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND;
+ *wire_overlay = DRW_pass_create("Wire Overlays Pass", state);
+ }
+
+ if (wire_outline) {
+ /* This pass can draw mesh outlines and/or fancy wireframe */
+ /* Fancy wireframes are not meant to be occluded (without Z offset) */
+ /* Outlines and Fancy Wires use the same VBO */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ *wire_outline = DRW_pass_create("Wire + Outlines Pass", state);
+ }
+
+ if (non_meshes) {
+ /* Non Meshes Pass (Camera, empties, lamps ...) */
+ DRWShadingGroup *grp;
+ struct Batch *geom;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ state |= DRW_STATE_WIRE;
+ *non_meshes = DRW_pass_create("Non Meshes Pass", state);
+
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* Empties */
+ geom = DRW_cache_plain_axes_get();
+ plain_axes = shgroup_instance(*non_meshes, geom);
+
+ geom = DRW_cache_cube_get();
+ cube = shgroup_instance(*non_meshes, geom);
+
+ geom = DRW_cache_circle_get();
+ circle = shgroup_instance(*non_meshes, geom);
+
+ geom = DRW_cache_empty_sphere_get();
+ sphere = shgroup_instance(*non_meshes, geom);
+
+ geom = DRW_cache_empty_cone_get();
+ cone = shgroup_instance(*non_meshes, geom);
+
+ geom = DRW_cache_single_arrow_get();
+ single_arrow = shgroup_instance(*non_meshes, geom);
+
+ geom = DRW_cache_single_line_get();
+ single_arrow_line = shgroup_instance(*non_meshes, geom);
+
+ geom = DRW_cache_single_arrow_get();
+ arrows = shgroup_instance(*non_meshes, geom);
+
+ /* Lamps */
+ lampCenterSize = (U.obcenter_dia + 1.5f) * U.pixelsize;
+ lampCircleRad = U.pixelsize * 9.0f;
+ lampCircleShadowRad = lampCircleRad + U.pixelsize * 3.0f;
+ /* TODO
+ * for now we create 3 times the same VBO with only lamp center coordinates
+ * but ideally we would only create it once */
+ lamp_center = shgroup_dynpoints_uniform_color(*non_meshes, colorLampNoAlpha, &lampCenterSize);
+ lamp_center_group = shgroup_dynpoints_uniform_color(*non_meshes, colorGroup, &lampCenterSize);
+
+ geom = DRW_cache_lamp_get();
+ lamp_circle = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleRad);
+ lamp_circle_shadow = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleShadowRad);
+
+ geom = DRW_cache_lamp_sunrays_get();
+ lamp_sunrays = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleRad);
+
+ lamp_groundline = shgroup_groundlines_uniform_color(*non_meshes, colorLamp);
+ lamp_groundpoint = shgroup_groundpoints_uniform_color(*non_meshes, colorLamp);
+
+ /* Stipple Wires */
+ grp = DRW_shgroup_create(sh, *non_meshes);
+ DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_2);
+
+ grp = DRW_shgroup_create(sh, *non_meshes);
+ DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
+
+ grp = DRW_shgroup_create(sh, *non_meshes);
+ DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_4);
+
+ /* Relationship Lines */
+ relationship_lines = shgroup_dynlines_uniform_color(*non_meshes, colorWire);
+ DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3);
+ }
+
+ if (ob_center) {
+ /* Object Center pass grouped by State */
+ DRWShadingGroup *grp;
+ static float colorDeselect[4], outlineColor[4];
+ static float outlineWidth, size;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT;
+ *ob_center = DRW_pass_create("Obj Center Pass", state);
+
+ outlineWidth = 1.0f * U.pixelsize;
+ size = U.obcenter_dia * U.pixelsize + outlineWidth;
+ //UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -80, colorActive);
+ //UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -80, colorSelect);
+ UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, colorDeselect);
+ UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor);
+
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+
+ /* Active */
+ grp = DRW_shgroup_point_batch_create(sh, *ob_center);
+ DRW_shgroup_uniform_float(grp, "size", &size, 1);
+ DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1);
+ DRW_shgroup_uniform_vec4(grp, "color", colorActive, 1);
+ DRW_shgroup_uniform_vec4(grp, "outlineColor", outlineColor, 1);
+ center_active = grp;
+
+ /* Select */
+ grp = DRW_shgroup_point_batch_create(sh, *ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", colorSelect, 1);
+ center_selected = grp;
+
+ /* Deselect */
+ grp = DRW_shgroup_point_batch_create(sh, *ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", colorDeselect, 1);
+ center_deselected = grp;
+ }
+}
+
+/* ******************************************** WIRES *********************************************** */
+
+/* TODO FINISH */
+/* Get the wire color theme_id of an object based on it's state
+ * **color is a way to get a pointer to the static color var associated */
+static int draw_object_wire_theme(Object *ob, float **color)
+{
+ const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
+ /* confusing logic here, there are 2 methods of setting the color
+ * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
+ *
+ * note: no theme yet for 'colindex' */
+ int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
+
+ if (//(scene->obedit == NULL) &&
+ ((G.moving & G_TRANSFORM_OBJ) != 0) &&
+ ((ob->base_flag & BASE_SELECTED) != 0))
+ {
+ theme_id = TH_TRANSFORM;
+ }
+ else {
+ /* Sets the 'theme_id' or fallback to wire */
+ if ((ob->flag & OB_FROMGROUP) != 0) {
+ if ((ob->base_flag & BASE_SELECTED) != 0) {
+ /* uses darker active color for non-active + selected */
+ theme_id = TH_GROUP_ACTIVE;
+
+ // if (scene->basact != base) {
+ // theme_shade = -16;
+ // }
+ }
+ else {
+ theme_id = TH_GROUP;
+ }
+ }
+ else {
+ if ((ob->base_flag & BASE_SELECTED) != 0) {
+ theme_id = //scene->basact == base ? TH_ACTIVE :
+ TH_SELECT;
+ }
+ else {
+ if (ob->type == OB_LAMP) theme_id = TH_LAMP;
+ else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER;
+ else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA;
+ else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY;
+ /* fallback to TH_WIRE */
+ }
+ }
+ }
+
+ if (color != NULL) {
+ switch (theme_id) {
+ case TH_WIRE_EDIT: *color = colorTransform; break;
+ case TH_ACTIVE: *color = colorActive; break;
+ case TH_SELECT: *color = colorSelect; break;
+ case TH_GROUP: *color = colorGroup; break;
+ case TH_GROUP_ACTIVE: *color = colorGroupActive; break;
+ case TH_TRANSFORM: *color = colorTransform; break;
+ case OB_SPEAKER: *color = colorSpeaker; break;
+ case OB_CAMERA: *color = colorCamera; break;
+ case OB_EMPTY: *color = colorEmpty; break;
+ case OB_LAMP: *color = colorLamp; break;
+ default: *color = colorWire; break;
+ }
+ }
+
+ return theme_id;
+}
+
+void DRW_shgroup_wire_overlay(DRWPass *wire_overlay, Object *ob)
+{
+#if 1
+ struct Batch *geom = DRW_cache_wire_overlay_get(ob);
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+
+ DRW_shgroup_call_add(grp, geom, ob->obmat);
+#else
+ static float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ struct Batch *geom = DRW_cache_wire_overlay_get(ob);
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
+ DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+
+ DRW_shgroup_call_add(grp, geom, ob->obmat);
+#endif
+}
+
+void DRW_shgroup_wire_outline(DRWPass *wire_outline, Object *ob,
+ const bool do_front, const bool do_back, const bool do_outline)
+{
+ GPUShader *sh;
+ struct Batch *geom = DRW_cache_wire_outline_get(ob);
+
+ /* Get color */
+ /* TODO get the right color depending on ob state (Groups, overides etc..) */
+ static float frontcol[4], backcol[4], color[4];
+ UI_GetThemeColor4fv(TH_ACTIVE, color);
+ copy_v4_v4(frontcol, color);
+ copy_v4_v4(backcol, color);
+ backcol[3] = 0.333f;
+ frontcol[3] = 0.667f;
+
+#if 1 /* New wire */
+
+ bool is_perps = DRW_viewport_is_persp_get();
+ static bool bTrue = true;
+ static bool bFalse = false;
+
+ /* Note (TODO) : this requires cache to be discarded on ortho/perp switch
+ * It may be preferable (or not depending on performance implication)
+ * to introduce a shader uniform switch */
+ if (is_perps) {
+ sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP);
+ }
+ else {
+ sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
+ }
+
+ if (do_front || do_back) {
+ bool *bFront = (do_front) ? &bTrue : &bFalse;
+ bool *bBack = (do_back) ? &bTrue : &bFalse;
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
+ DRW_shgroup_state_set(grp, DRW_STATE_WIRE);
+ DRW_shgroup_uniform_vec4(grp, "frontColor", frontcol, 1);
+ DRW_shgroup_uniform_vec4(grp, "backColor", backcol, 1);
+ DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1);
+ DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1);
+ DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1);
+ DRW_shgroup_call_add(grp, geom, ob->obmat);
+ }
+
+ if (do_outline) {
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
+ DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
+ DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1);
+ DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1);
+ DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1);
+ DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1);
+
+ DRW_shgroup_call_add(grp, geom, ob->obmat);
+ }
+
+#else /* Old (flat) wire */
+
+ sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
+ DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
+ DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1);
+
+ DRW_shgroup_call_add(grp, geom, ob->obmat);
+#endif
+
+}
+
+/* ***************************** NON MESHES ********************** */
+
+static void DRW_draw_lamp(Object *ob)
+{
+ Lamp *la = ob->data;
+ float *color;
+ int theme_id = draw_object_wire_theme(ob, &color);
+
+ /* Don't draw the center if it's selected or active */
+ if (theme_id == TH_GROUP)
+ DRW_shgroup_dynamic_call_add(lamp_center_group, ob->obmat[3]);
+ else if (theme_id == TH_LAMP)
+ DRW_shgroup_dynamic_call_add(lamp_center, ob->obmat[3]);
+
+ /* First circle */
+ DRW_shgroup_dynamic_call_add(lamp_circle, ob->obmat[3], color);
+
+ /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
+ if (la->type != LA_HEMI) {
+ DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color);
+ }
+
+ /* Sunrays */
+ if (la->type == LA_SUN) {
+ DRW_shgroup_dynamic_call_add(lamp_sunrays, ob->obmat[3], color);
+ }
+
+ /* Line and point going to the ground */
+ DRW_shgroup_dynamic_call_add(lamp_groundline, ob->obmat[3]);
+ DRW_shgroup_dynamic_call_add(lamp_groundpoint, ob->obmat[3]);
+}
+
+static void DRW_draw_empty(Object *ob)
+{
+ float *color;
+ draw_object_wire_theme(ob, &color);
+
+ switch (ob->empty_drawtype) {
+ case OB_PLAINAXES:
+ DRW_shgroup_dynamic_call_add(plain_axes, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_SINGLE_ARROW:
+ DRW_shgroup_dynamic_call_add(single_arrow, color, &ob->empty_drawsize, ob->obmat);
+ DRW_shgroup_dynamic_call_add(single_arrow_line, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_CUBE:
+ DRW_shgroup_dynamic_call_add(cube, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_CIRCLE:
+ DRW_shgroup_dynamic_call_add(circle, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_EMPTY_SPHERE:
+ DRW_shgroup_dynamic_call_add(sphere, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_EMPTY_CONE:
+ DRW_shgroup_dynamic_call_add(cone, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_ARROWS:
+ DRW_shgroup_dynamic_call_add(arrows, color, &ob->empty_drawsize, ob->obmat);
+ /* TODO Missing axes names */
+ break;
+ }
+}
+
+void DRW_shgroup_non_meshes(DRWPass *UNUSED(non_meshes), Object *ob)
+{
+ switch (ob->type) {
+ case OB_LAMP:
+ DRW_draw_lamp(ob);
+ break;
+ case OB_CAMERA:
+ case OB_EMPTY:
+ DRW_draw_empty(ob);
+ default:
+ break;
+ }
+}
+
+void DRW_shgroup_relationship_lines(DRWPass *UNUSED(non_meshes), Object *ob)
+{
+ if (ob->parent) {
+ DRW_shgroup_dynamic_call_add(relationship_lines, ob->obmat[3]);
+ DRW_shgroup_dynamic_call_add(relationship_lines, ob->parent->obmat[3]);
+ }
+}
+
+/* ***************************** COMMON **************************** */
+
+void DRW_shgroup_object_center(DRWPass *UNUSED(ob_center), Object *ob)
+{
+ if ((ob->base_flag & BASE_SELECTED) != 0) {
+ DRW_shgroup_dynamic_call_add(center_selected, ob->obmat[3]);
+ }
+ else if (0) {
+ DRW_shgroup_dynamic_call_add(center_deselected, ob->obmat[3]);
+ }
+}
diff --git a/source/blender/draw/intern/draw_mode_pass.h b/source/blender/draw/intern/draw_mode_pass.h
new file mode 100644
index 00000000000..d11213ec8a2
--- /dev/null
+++ b/source/blender/draw/intern/draw_mode_pass.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_mode_pass.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_MODE_PASS_H__
+#define __DRAW_MODE_PASS_H__
+
+#include "DRW_render.h"
+
+struct DRWPass;
+struct Batch;
+struct Object;
+
+void DRW_pass_setup_common(struct DRWPass **wire_overlay, struct DRWPass **wire_outline, struct DRWPass **non_meshes, struct DRWPass **ob_center);
+
+void DRW_shgroup_wire_overlay(struct DRWPass *wire_overlay, struct Object *ob);
+void DRW_shgroup_wire_outline(
+ struct DRWPass *wire_outline, struct Object *ob, const bool do_front, const bool do_back, const bool do_outline);
+
+void DRW_shgroup_non_meshes(struct DRWPass *non_meshes, struct Object *ob);
+void DRW_shgroup_relationship_lines(struct DRWPass *non_meshes, struct Object *ob);
+void DRW_shgroup_object_center(struct DRWPass *ob_center, struct Object *ob);
+
+#endif /* __DRAW_MODE_PASS_H__ */ \ No newline at end of file
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 1559512d713..7e804a5bbfc 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -47,6 +47,7 @@ if(WITH_BLENDER)
add_subdirectory(space_graph)
add_subdirectory(space_image)
add_subdirectory(space_info)
+ add_subdirectory(space_collections)
add_subdirectory(space_logic)
add_subdirectory(space_nla)
add_subdirectory(space_node)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 26674278a5e..f41c4741eff 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -124,7 +124,7 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
/* 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_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
@@ -143,15 +143,14 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
-
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fv(color);
-
+
/* no rounded corner - just rectangular box */
immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
@@ -233,8 +232,7 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
@@ -442,7 +440,7 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
* - 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_3fvAlpha(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for summary entries */
@@ -631,7 +629,7 @@ static bAnimChannelType ACF_SCENE =
static int acf_object_icon(bAnimListElem *ale)
{
- Base *base = (Base *)ale->data;
+ BaseLegacy *base = (BaseLegacy *)ale->data;
Object *ob = base->object;
/* icon depends on object-type */
@@ -666,7 +664,7 @@ static int acf_object_icon(bAnimListElem *ale)
/* name for object */
static void acf_object_name(bAnimListElem *ale, char *name)
{
- Base *base = (Base *)ale->data;
+ BaseLegacy *base = (BaseLegacy *)ale->data;
Object *ob = base->object;
/* just copy the name... */
@@ -686,7 +684,7 @@ static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN
/* check if some setting exists for this channel */
static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
{
- Base *base = (Base *)ale->data;
+ BaseLegacy *base = (BaseLegacy *)ale->data;
Object *ob = base->object;
switch (setting) {
@@ -743,7 +741,7 @@ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
/* get pointer to the setting */
static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
{
- Base *base = (Base *)ale->data;
+ BaseLegacy *base = (BaseLegacy *)ale->data;
Object *ob = base->object;
/* clear extra return data first */
@@ -831,7 +829,7 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
/* 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_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for group entries */
@@ -1087,7 +1085,7 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
/* 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_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_TRIANGLE_FAN, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
}
/* name for nla controls expander entries */
@@ -3441,7 +3439,7 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y
/* 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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color);
}
/* name for nla action entries */
@@ -3864,8 +3862,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* for F-Curves, draw color-preview of curve behind checkbox */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
FCurve *fcu = (FCurve *)ale->data;
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -3903,31 +3900,32 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
if (acf->name && !achannel_is_being_renamed(ac, acf, channel_index)) {
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
-
+ unsigned char col[4];
+
/* set text color */
/* XXX: if active, highlight differently? */
+
if (selected)
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4ubv(TH_TEXT_HI, col);
else
- UI_ThemeColor(TH_TEXT);
-
+ UI_GetThemeColor4ubv(TH_TEXT, col);
+
/* get name */
acf->name(ale, name);
offset += 3;
- UI_fontstyle_draw_simple(fstyle, offset, ytext, name);
+ UI_fontstyle_draw_simple(fstyle, offset, ytext, name, col);
/* draw red underline if channel is disabled */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* FIXME: replace hardcoded color here, and check on extents! */
immUniformColor3f(1.0f, 0.0f, 0.0f);
- glLineWidth(2.0);
+ glLineWidth(2.0f);
immBegin(GL_LINES, 2);
immVertex2f(pos, (float)offset, yminc);
@@ -3948,8 +3946,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
short draw_sliders = 0;
float ymin_ofs = 0.0f;
float color[3];
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 117b8549712..22578b6a518 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -57,6 +57,7 @@
#include "BKE_context.h"
#include "BKE_mask.h"
#include "BKE_global.h"
+#include "BKE_scene.h"
#include "UI_view2d.h"
@@ -2682,31 +2683,31 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
{
bDopeSheet *ads = (bDopeSheet *)ac->data;
Scene *sce = (Scene *)ads->source;
- Base *base = (Base *)ale->data;
+ BaseLegacy *base = (BaseLegacy *)ale->data;
Object *ob = base->object;
AnimData *adt = ob->adt;
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
- base->flag ^= SELECT;
- ob->flag = base->flag;
+ base->flag_legacy ^= SELECT;
+ BKE_scene_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
- Base *b;
+ BaseLegacy *b;
/* deselect all */
/* TODO: should this deselect all other types of channels too? */
for (b = sce->base.first; b; b = b->next) {
- b->flag &= ~SELECT;
- b->object->flag = b->flag;
+ b->flag_legacy &= ~SELECT;
+ BKE_scene_base_flag_sync_from_base(b);
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
}
/* select object now */
- base->flag |= SELECT;
+ base->flag_legacy |= SELECT;
ob->flag |= SELECT;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 58b9b8eba91..2b830657923 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -71,6 +71,9 @@
static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned char col[4];
float xscale, yscale, x, y;
char numstr[32] = " t"; /* t is the character to start replacing from */
int slen;
@@ -96,9 +99,6 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
/* get starting coordinates for drawing */
x = cfra * xscale;
y = 0.9f * U.widget_unit;
-
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -107,11 +107,11 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
immRectf(pos, x, y, x + slen, y + 0.75f * U.widget_unit);
immUnbindProgram();
-
+
/* draw current frame number - black text */
- UI_ThemeColor(TH_TEXT);
- UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
-
+ UI_GetThemeColor4ubv(TH_TEXT, col);
+ UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr, col);
+
/* restore view transform */
glScalef(xscale, 1.0, 1.0);
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index c12a050e9ba..7b6d30469a4 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -601,7 +601,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
}
case ANIMTYPE_OBJECT:
{
- Base *base = (Base *)data;
+ BaseLegacy *base = (BaseLegacy *)data;
Object *ob = base->object;
ale->flag = ob->flag;
@@ -1683,7 +1683,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
if (ads->filterflag & ADS_FILTER_GP_3DONLY) {
Scene *scene = (Scene *)ads->source;
- Base *base;
+ BaseLegacy *base;
/* Active scene's GPencil block first - No parent item needed... */
if (scene->gpd) {
@@ -1714,7 +1714,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
}
/* check selection and object type filters */
- if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == scene->basact)*/) ) {
+ if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == scene->basact)*/) ) {
/* only selected should be shown */
continue;
}
@@ -2223,7 +2223,7 @@ typedef struct tAnimFilterModifiersContext {
/* dependency walker callback for modifier dependencies */
-static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cd_flag))
+static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cb_flag))
{
tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr;
ID *owner_id = &ob->id;
@@ -2573,7 +2573,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
}
/* get animation channels from object2 */
-static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, BaseLegacy *base, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
Object *ob = base->object;
@@ -2629,7 +2629,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by selection */
// XXX: double-check on this - most of the time, a lot of tools need to filter out these channels!
- if (ANIMCHANNEL_SELOK((base->flag & SELECT))) {
+ if (ANIMCHANNEL_SELOK((base->flag_legacy & SELECT))) {
/* check if filtering by active status */
if (ANIMCHANNEL_ACTIVEOK(ob)) {
ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob);
@@ -2853,7 +2853,7 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a
}
/* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */
-static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base, int filter_mode)
+static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy *base, int filter_mode)
{
Object *ob = base->object;
@@ -2906,7 +2906,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base
}
/* check selection and object type filters */
- if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/)) {
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == sce->basact)*/)) {
/* only selected should be shown */
return false;
}
@@ -2927,28 +2927,28 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base
/* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */
static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
{
- const Base *b1 = *((const Base **)base1_ptr);
- const Base *b2 = *((const Base **)base2_ptr);
+ const BaseLegacy *b1 = *((const BaseLegacy **)base1_ptr);
+ const BaseLegacy *b2 = *((const BaseLegacy **)base2_ptr);
return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
}
/* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */
-static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases)
+static BaseLegacy **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases)
{
/* Create an array with space for all the bases, but only containing the usable ones */
size_t tot_bases = BLI_listbase_count(&scene->base);
size_t num_bases = 0;
- Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases");
- for (Base *base = scene->base.first; base; base = base->next) {
+ BaseLegacy **sorted_bases = MEM_mallocN(sizeof(BaseLegacy *) * tot_bases, "Dopesheet Usable Sorted Bases");
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
sorted_bases[num_bases++] = base;
}
}
/* Sort this list of pointers (based on the names) */
- qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp);
+ qsort(sorted_bases, num_bases, sizeof(BaseLegacy *), ds_base_sorting_cmp);
/* Return list of sorted bases */
*r_usable_bases = num_bases;
@@ -3002,7 +3002,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
{
/* Filter list of bases (i.e. objects), sort them, then add their contents normally... */
// TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort...
- Base **sorted_bases;
+ BaseLegacy **sorted_bases;
size_t num_bases;
sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases);
@@ -3022,7 +3022,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
/* Filter and add contents of each base (i.e. object) without them sorting first
* NOTE: This saves performance in cases where order doesn't matter
*/
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
/* since we're still here, this object should be usable */
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 823cde75334..ef9c2ced580 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -36,7 +36,7 @@
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
-#include "BLI_math_base.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -380,19 +380,20 @@ static void draw_marker(
/* and the marker name too, shifted slightly to the top-right */
if (marker->name[0]) {
+ unsigned char text_col[4];
float x, y;
/* minimal y coordinate which wouldn't be occluded by scroll */
int min_y = 17.0f * UI_DPI_FAC;
if (marker->flag & SELECT) {
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
x = xpos + 4.0f * UI_DPI_FAC;
y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
y = max_ii(y, min_y);
}
else {
- UI_ThemeColor(TH_TEXT);
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
x = xpos + 8.0f * UI_DPI_FAC;
y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
@@ -406,14 +407,11 @@ static void draw_marker(
#ifdef DURIAN_CAMERA_SWITCH
if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
- float col[4];
- glGetFloatv(GL_CURRENT_COLOR, col);
- col[3] = 0.4;
- glColor4fv(col);
+ text_col[3] = 100;
}
#endif
- UI_fontstyle_draw_simple(fstyle, x, y, marker->name);
+ UI_fontstyle_draw_simple(fstyle, x, y, marker->name, text_col);
}
}
@@ -1124,7 +1122,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
if (camera) {
Scene *scene = CTX_data_scene(C);
- Base *base;
+ BaseLegacy *base;
TimeMarker *marker;
int sel = 0;
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 5f675e690b9..c8d141eab07 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -52,7 +52,8 @@
#include "BKE_fcurve.h"
-#include "BIF_gl.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -463,49 +464,15 @@ bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys)
/* *************************** Keyframe Drawing *************************** */
-/* coordinates for diamond shape */
-static const float _unit_diamond_shape[4][2] = {
- {0.0f, 1.0f}, /* top vert */
- {1.0f, 0.0f}, /* mid-right */
- {0.0f, -1.0f}, /* bottom vert */
- {-1.0f, 0.0f} /* mid-left */
-};
-
-/* draw a simple diamond shape with OpenGL */
-void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha)
+void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha,
+ unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id)
{
- static GLuint displist1 = 0;
- static GLuint displist2 = 0;
-
- /* initialize 2 display lists for diamond shape - one empty, one filled */
- if (displist1 == 0) {
- displist1 = glGenLists(1);
- glNewList(displist1, GL_COMPILE);
-
- glBegin(GL_LINE_LOOP);
- glVertex2fv(_unit_diamond_shape[0]);
- glVertex2fv(_unit_diamond_shape[1]);
- glVertex2fv(_unit_diamond_shape[2]);
- glVertex2fv(_unit_diamond_shape[3]);
- glEnd();
-
- glEndList();
- }
- if (displist2 == 0) {
- displist2 = glGenLists(1);
- glNewList(displist2, GL_COMPILE);
-
- glBegin(GL_QUADS);
- glVertex2fv(_unit_diamond_shape[0]);
- glVertex2fv(_unit_diamond_shape[1]);
- glVertex2fv(_unit_diamond_shape[2]);
- glVertex2fv(_unit_diamond_shape[3]);
- glEnd();
-
- glEndList();
- }
-
- /* tweak size of keyframe shape according to type of keyframe
+ bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH);
+ bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH);
+
+ if (!(draw_fill || draw_outline)) return; /* TODO: assert this? */
+
+ /* tweak size of keyframe shape according to type of keyframe
* - 'proper' keyframes have key_type = 0, so get drawn at full size
*/
switch (key_type) {
@@ -513,120 +480,93 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel,
break;
case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
- hsize *= 0.85f;
+ size *= 0.85f;
break;
case BEZT_KEYTYPE_MOVEHOLD: /* slightly smaller than normal keyframes (but by less than for breakdowns) */
- //hsize *= 0.72f;
- hsize *= 0.95f;
+ //size *= 0.72f;
+ size *= 0.95f;
break;
case BEZT_KEYTYPE_EXTREME: /* slightly larger */
- hsize *= 1.2f;
+ size *= 1.2f;
break;
default:
- hsize -= 0.5f * key_type;
- break;
+ size -= 0.5f * key_type;
}
-
- /* adjust view transform before starting */
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * hsize, hsize, 1.0f);
-
- /* anti-aliased lines for more consistent appearance */
- glEnable(GL_LINE_SMOOTH);
-
+
+ unsigned char fill_col[4];
+ unsigned char outline_col[4];
+
/* draw! */
- if (ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH)) {
- float inner_col[4];
-
+ if (draw_fill) {
/* get interior colors from theme (for selected and unselected only) */
switch (key_type) {
case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
- {
- if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN_SELECT, inner_col);
- else UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN, inner_col);
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col);
break;
- }
case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
- {
- if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME_SELECT, inner_col);
- else UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME, inner_col);
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col);
break;
- }
case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
- {
- if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_JITTER_SELECT, inner_col);
- else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col);
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col);
break;
- }
case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
- {
/* XXX: Should these get their own theme options instead? */
- if (sel) UI_GetThemeColorShade4fv(TH_STRIP_SELECT, 35, inner_col);
- else UI_GetThemeColorShade4fv(TH_STRIP, 50, inner_col);
-
- inner_col[3] = 1.0f; /* full opacity, to avoid problems with visual glitches */
+ if (sel) UI_GetThemeColorShade3ubv(TH_STRIP_SELECT, 35, fill_col);
+ else UI_GetThemeColorShade3ubv(TH_STRIP, 50, fill_col);
+ fill_col[3] = 255; /* full opacity, to avoid problems with visual glitches */
break;
- }
case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
default:
- {
- if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME_SELECT, inner_col);
- else UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME, inner_col);
- break;
- }
+ UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col);
}
/* NOTE: we don't use the straight alpha from the theme, or else effects such as
* graying out protected/muted channels doesn't work correctly!
*/
- inner_col[3] *= alpha;
- glColor4fv(inner_col);
-
- /* draw the "filled in" interior poly now */
- glCallList(displist2);
+ fill_col[3] *= alpha;
+
+ if (!draw_outline) {
+ /* force outline color to match */
+ outline_col[0] = fill_col[0];
+ outline_col[1] = fill_col[1];
+ outline_col[2] = fill_col[2];
+ outline_col[3] = fill_col[3];
+ }
}
-
- if (ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH)) {
- float border_col[4];
-
+
+ if (draw_outline) {
/* exterior - black frame */
- if (sel) UI_GetThemeColor4fv(TH_KEYBORDER_SELECT, border_col);
- else UI_GetThemeColor4fv(TH_KEYBORDER, border_col);
-
- border_col[3] *= alpha;
- glColor4fv(border_col);
-
- glCallList(displist1);
+ UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col);
+ outline_col[3] *= alpha;
+
+ if (!draw_fill) {
+ /* fill color needs to be (outline.rgb, 0) */
+ fill_col[0] = outline_col[0];
+ fill_col[1] = outline_col[1];
+ fill_col[2] = outline_col[2];
+ fill_col[3] = 0;
+ }
}
-
- glDisable(GL_LINE_SMOOTH);
-
- /* restore view transform */
- glScalef(xscale / hsize, 1.0f / hsize, 1.0f);
- glTranslatef(-x, -y, 0.0f);
+
+ immAttrib1f(size_id, size);
+ immAttrib4ubv(color_id, fill_col);
+ immAttrib4ubv(outline_color_id, outline_col);
+ immVertex2f(pos_id, x, y);
}
static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
{
- ActKeyColumn *ak;
- ActKeyBlock *ab;
- float alpha;
- float xscale;
-
- const float iconsize = (U.widget_unit / 4.0f) * yscale_fac;
- const float mhsize = iconsize * 0.7f;
+ const float iconsize = U.widget_unit * 0.25f * yscale_fac;
+ const float mhsize = iconsize * 0.7f;
glEnable(GL_BLEND);
- /* get View2D scaling factor */
- UI_view2d_scale_get(v2d, &xscale, NULL);
-
/* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
/* TODO: allow this opacity factor to be themed? */
- alpha = (channelLocked) ? 0.25f : 1.0f;
+ float alpha = channelLocked ? 0.25f : 1.0f;
/* draw keyblocks */
if (blocks) {
@@ -644,45 +584,59 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
sel_mhcol[3] *= 0.8f;
copy_v4_v4(unsel_mhcol, unsel_color);
unsel_mhcol[3] *= 0.8f;
-
+
+ unsigned int pos_id = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */
- for (ab = blocks->first; ab; ab = ab->next) {
+ for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
if (actkeyblock_is_valid(ab, keys)) {
if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
/* draw "moving hold" long-keyframe block - slightly smaller */
- if (ab->sel)
- glColor4fv(sel_mhcol);
- else
- glColor4fv(unsel_mhcol);
-
- glRectf(ab->start, ypos - mhsize, ab->end, ypos + mhsize);
+ immUniformColor4fv(ab->sel ? sel_mhcol : unsel_mhcol);
+ immRectf(pos_id, ab->start, ypos - mhsize, ab->end, ypos + mhsize);
}
else {
/* draw standard long-keyframe block */
- if (ab->sel)
- glColor4fv(sel_color);
- else
- glColor4fv(unsel_color);
-
- glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
+ immUniformColor4fv(ab->sel ? sel_color : unsel_color);
+ immRectf(pos_id, ab->start, ypos - iconsize, ab->end, ypos + iconsize);
}
}
}
+ immUnbindProgram();
}
- /* draw keys */
if (keys) {
- for (ak = keys->first; ak; ak = ak->next) {
+ /* count keys */
+ unsigned int key_ct = 0;
+ for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
/* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
* - this might give some improvements, since we current have to flip between view/region matrices
*/
- if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
- continue;
-
- /* draw using OpenGL - uglier but faster */
- /* NOTE1: a previous version of this didn't work nice for some intel cards
- * NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
- draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha);
+ if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax))
+ key_ct++;
+ }
+
+ if (key_ct > 0) {
+ /* draw keys */
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT);
+ unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+ unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(PRIM_POINTS, key_ct);
+
+ for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
+ if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
+ draw_keyframe_shape(ak->cfra, ypos, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha,
+ pos_id, size_id, color_id, outline_color_id);
+ }
+ }
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
}
}
@@ -938,7 +892,7 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl
int filter;
bAnimListElem dummychan = {NULL};
- Base dummybase = {NULL};
+ BaseLegacy dummybase = {NULL};
if (ob == NULL)
return;
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 4571df0f077..f4922fec385 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -193,7 +193,7 @@ static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *o
int ret = 0;
bAnimListElem dummychan = {NULL};
- Base dummybase = {NULL};
+ BaseLegacy dummybase = {NULL};
if (ob == NULL)
return 0;
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index b39b4bd81ee..d75193a46ff 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -37,7 +37,7 @@ struct wmOperatorType;
struct bContext;
struct Scene;
struct Object;
-struct Base;
+struct BaseLegacy;
struct bAction;
struct bPoseChannel;
@@ -248,7 +248,7 @@ void armature_select_mirrored(struct bArmature *arm);
void armature_tag_unselect(struct bArmature *arm);
void *get_nearest_bone(struct bContext *C, short findunsel, int x, int y);
-void *get_bone_from_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest);
+void *get_bone_from_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest);
int bone_looper(struct Object *ob, struct Bone *bone, void *data,
int (*bone_func)(struct Object *, struct Bone *, void *));
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 1c342657eec..0dc97483dfc 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -50,6 +50,7 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -400,7 +401,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
/* Free the old object data */
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
CTX_DATA_END;
@@ -579,6 +580,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
Object *oldob, *newob;
Base *oldbase, *newbase;
@@ -602,14 +604,18 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* TODO: use context iterators for this? */
CTX_DATA_BEGIN(C, Base *, base, visible_bases)
{
- if (base->object == obedit) base->flag |= SELECT;
- else base->flag &= ~SELECT;
+ if (base->object == obedit) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ else {
+ ED_object_base_select(base, BA_DESELECT);
+ }
}
CTX_DATA_END;
/* 1) store starting settings and exit editmode */
oldob = obedit;
- oldbase = BASACT;
+ oldbase = sl->basact;
oldob->mode &= ~OB_MODE_POSE;
//oldbase->flag &= ~OB_POSEMODE;
@@ -617,13 +623,13 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ED_armature_edit_free(obedit->data);
/* 2) duplicate base */
- newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
+ newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
DAG_relations_tag_update(bmain);
newob = newbase->object;
- newbase->flag &= ~SELECT;
-
-
+ newbase->flag &= ~BASE_SELECTED;
+
+
/* 3) remove bones that shouldn't still be around on both armatures */
separate_armature_bones(oldob, 1);
separate_armature_bones(newob, 0);
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index e9946abba0b..1f994a7f13e 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -74,7 +74,7 @@ Bone *get_indexed_bone(Object *ob, int index)
/* See if there are any selected bones in this buffer */
/* only bones from base are checked on */
-void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest)
+void *get_bone_from_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest)
{
Object *obedit = scene->obedit; // XXX get from context
Bone *bone;
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index cc4c1809fbc..4d9ba351c3a 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -142,7 +142,7 @@ void BIF_makeListTemplates(const bContext *C)
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
- Base *base;
+ BaseLegacy *base;
int index = 0;
if (TEMPLATES_HASH != NULL) {
@@ -970,6 +970,9 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
ToolSettings *ts = CTX_data_tool_settings(C);
int point_added = 0;
+ /* TODO: Since the function `ED_transform_snap_object_context_create_view3d` creates a cache,
+ * the ideal would be to call this function only at the beginning of the snap operation,
+ * or at the beginning of the operator itself */
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
CTX_data_main(C), CTX_data_scene(C), 0,
CTX_wm_region(C), CTX_wm_view3d(C));
@@ -1038,6 +1041,8 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
}
}
+ /* TODO: The ideal would be to call this function only once.
+ * At the end of the operator */
ED_transform_snap_object_context_destroy(snap_context);
return point_added;
}
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 44470c1f827..903d309cb1f 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -132,7 +132,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
/* called from editview.c, for mode-less pose selection */
/* assumes scene obact and basact is still on old situation */
-int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits,
+int ED_do_pose_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits,
bool extend, bool deselect, bool toggle, bool do_nearest)
{
Object *ob = base->object;
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index e9fd5fb5a43..6b5a5d81d32 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -50,6 +50,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -1270,6 +1271,7 @@ static int separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *oldob, *newob;
Base *oldbase, *newbase;
Curve *oldcu, *newcu;
@@ -1297,7 +1299,7 @@ static int separate_exec(bContext *C, wmOperator *op)
}
/* 2. duplicate the object and data */
- newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */
+ newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, 0); /* 0 = fully linked */
DAG_relations_tag_update(bmain);
newob = newbase->object;
@@ -6024,7 +6026,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
}
}
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
}
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 34e026a3ef4..4720b76342c 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -48,6 +48,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "curve_intern.h"
#include "UI_resources.h"
@@ -514,30 +516,45 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
}
{
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, coord_array);
-
- cpack(0x0);
+ imm_cpack(0x0);
+ immBegin(GL_LINE_STRIP, stroke_len);
glLineWidth(3.0f);
- glDrawArrays(GL_LINE_STRIP, 0, stroke_len);
- if (v3d->zbuf)
+ if (v3d->zbuf) {
glDisable(GL_DEPTH_TEST);
+ }
+
+ for (int i = 0; i < stroke_len; i++) {
+ immVertex3fv(pos, coord_array[i]);
+ }
+
+ immEnd();
- cpack(0xffffffff);
+ imm_cpack(0xffffffff);
+ immBegin(GL_LINE_STRIP, stroke_len);
glLineWidth(1.0f);
- glDrawArrays(GL_LINE_STRIP, 0, stroke_len);
- if (v3d->zbuf)
- glEnable(GL_DEPTH_TEST);
+ for (int i = 0; i < stroke_len; i++) {
+ immVertex3fv(pos, coord_array[i]);
+ }
+
+ immEnd();
- glDisableClientState(GL_VERTEX_ARRAY);
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ }
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
+
+ immUnbindProgram();
}
MEM_freeN(coord_array);
@@ -686,6 +703,7 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
}
else {
cdd->vc.scene = CTX_data_scene(C);
+ cdd->vc.sl = CTX_data_scene_layer(C);
cdd->vc.obedit = CTX_data_edit_object(C);
}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 57e731874b4..d86091aaa77 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -420,6 +420,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Curve *cu;
Object *obedit;
Base *base;
@@ -429,8 +430,8 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
int a;
float rot[3] = {0.f, 0.f, 0.f};
- obedit = BKE_object_add(bmain, scene, OB_FONT, NULL);
- base = scene->basact;
+ obedit = BKE_object_add(bmain, scene, sl, OB_FONT, NULL);
+ base = sl->basact;
/* seems to assume view align ? TODO - look into this, could be an operator option */
ED_object_base_init_transform(C, base, NULL, rot);
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index e8a812817d1..05eb51fb02f 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -1563,13 +1563,15 @@ static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
const char *printable = IFACE_("GPencil Stroke Editing");
float printable_size[2];
- BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+ int font_id = BLF_default();
+
+ BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
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);
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
#ifdef WITH_INTERNATIONAL
BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#else
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index d0f68c4b8f3..505114869ac 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1128,7 +1128,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
Object *ob;
Curve *cu;
Nurb *nu = NULL;
- Base *base_orig = BASACT, *base_new = NULL;
+ BaseLegacy *base_orig = BASACT, *base_new = NULL;
float minmax_weights[2] = {1.0f, 0.0f};
/* camera framing */
@@ -1217,7 +1217,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
/* set the layer and select */
base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
- base_new->flag = ob->flag = base_new->flag | SELECT;
+ base_new->flag_legacy |= SELECT;
+ BKE_scene_base_flag_sync_from_base(base_new);
}
/* --- */
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 76e85f20c36..e3b6b748227 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -204,7 +204,7 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C)
// XXX: this should be removed... We really shouldn't duplicate logic like this!
bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d)
{
- Base *base = scene->basact;
+ BaseLegacy *base = scene->basact;
bGPdata *gpd = NULL;
/* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
* to be consistent with ED_gpencil_data_get_active's behavior.
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index db0ec6a2076..87086addf52 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -49,6 +49,7 @@ struct ColorManagedDisplaySettings;
void fdrawline(float x1, float y1, float x2, float y2); /* DEPRECATED */
void fdrawbox(float x1, float y1, float x2, float y2); /* DEPRECATED */
+void fdrawbox_filled(float x1, float y1, float x2, float y2);
void sdrawline(int x1, int y1, int x2, int y2); /* DEPRECATED */
void sdrawbox(int x1, int y1, int x2, int y2); /* DEPRECATED */
@@ -209,6 +210,24 @@ void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int forma
float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
/**
+ * immDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the
+ * image using textures, which can be tremendously faster on low-end
+ * cards, and also avoids problems with the raster position being
+ * clipped when offscreen. Pixel unpacking parameters and
+ * the glPixelZoom values are _not_ respected.
+ *
+ * \attention This routine makes many assumptions: the rect data
+ * is expected to be in RGBA byte or float format, and the
+ * modelview and projection matrices are assumed to define a
+ * 1-to-1 mapping to screen space.
+ */
+void immDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
+ float xzoom, float yzoom, float color[4]);
+void immDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
+ float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
+ float xzoom, float yzoom, float color[4]);
+
+/**
* glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef.
* only RGBA
* needs glaDefine2DArea to be set.
@@ -222,6 +241,11 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
+void immDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
+ float xzoom, float yzoom, float color[4]);
+void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
+ float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
+ float xzoom, float yzoom, float color[4]);
/* 2D Drawing Assistance */
/** Define a 2D area (viewport, scissor, matrices) for OpenGL rendering.
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 7ad61671b1b..3bde01a1bdd 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -35,7 +35,7 @@ extern "C" {
#endif
struct bArmature;
-struct Base;
+struct BaseLegacy;
struct bContext;
struct Bone;
struct bPoseChannel;
@@ -44,6 +44,7 @@ struct ListBase;
struct MeshDeformModifierData;
struct DerivedMesh;
struct Object;
+struct Base;
struct ReportList;
struct Scene;
struct ViewContext;
@@ -130,7 +131,7 @@ void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
void ED_armature_deselect_all(struct Object *obedit);
void ED_armature_deselect_all_visible(struct Object *obedit);
-int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer,
+int ED_do_pose_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer,
short hits, bool extend, bool deselect, bool toggle, bool do_nearest);
bool ED_armature_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
int join_armature_exec(struct bContext *C, struct wmOperator *op);
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index c478a8b17e5..8eef016a846 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -108,8 +108,10 @@ typedef enum eKeyframeShapeDrawOpts {
KEYFRAME_SHAPE_BOTH
} eKeyframeShapeDrawOpts;
-/* draw simple diamond-shape keyframe (with OpenGL) */
-void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha);
+/* draw simple diamond-shape keyframe */
+/* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND, immBegin(PRIM_POINTS, n), then call this n times */
+void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha,
+ unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id);
/* ******************************* Methods ****************************** */
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index f7b9d6b4f9e..b4cf96f27bf 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -75,7 +75,7 @@ void ED_init_custom_node_socket_type(struct bNodeSocketType *stype);
void ED_init_standard_node_socket_type(struct bNodeSocketType *stype);
void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
-void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border);
+void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos);
/* node_draw.c */
void ED_node_tree_update(const struct bContext *C);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 04ff5692717..4d79a42e64e 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -35,14 +35,16 @@
extern "C" {
#endif
-struct Base;
+struct BaseLegacy;
struct EnumPropertyItem;
struct ID;
struct Main;
struct ModifierData;
struct Object;
+struct Base;
struct ReportList;
struct Scene;
+struct SceneLayer;
struct bConstraint;
struct bContext;
struct bPoseChannel;
@@ -53,6 +55,7 @@ struct wmOperatorType;
struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
+struct LayerTree;
/* object_edit.c */
struct Object *ED_object_context(struct bContext *C); /* context.object */
@@ -89,7 +92,6 @@ bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct
struct Object *par, int partype, const bool xmirror, const bool keep_transform,
const int vert_par[3]);
void ED_object_parent_clear(struct Object *ob, const int type);
-struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
@@ -98,14 +100,20 @@ void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMa
const bool do_connected);
/* send your own notifier for select! */
-void ED_base_object_select(struct Base *base, short mode);
+void ED_base_object_select(struct BaseLegacy *base, short mode);
/* includes notifier */
-void ED_base_object_activate(struct bContext *C, struct Base *base);
+void ED_base_object_activate(struct bContext *C, struct BaseLegacy *base);
+
+void ED_object_base_select(struct Base *base, short mode);
+void ED_object_base_activate(struct bContext *C, struct Base *base);
-void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base);
+void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
+
+void ED_base_object_sync_from_base(struct BaseLegacy *base, struct Object *ob);
+void ED_base_object_sync_from_object(struct BaseLegacy *base, struct Object *ob);
/* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */
-struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag);
+struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct Base *base, int dupflag);
void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
@@ -191,7 +199,7 @@ 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);
+ struct SceneLayer *sl, 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_screen.h b/source/blender/editors/include/ED_screen.h
index f5f66a07aea..01be63919be 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -162,6 +162,7 @@ int ED_operator_image_active(struct bContext *C);
int ED_operator_nla_active(struct bContext *C);
int ED_operator_logic_active(struct bContext *C);
int ED_operator_info_active(struct bContext *C);
+int ED_operator_collections_active(struct bContext *C);
int ED_operator_console_active(struct bContext *C);
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index d268c578cf2..b754e1ba20f 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -58,6 +58,7 @@ void ED_spacetype_logic(void);
void ED_spacetype_console(void);
void ED_spacetype_userpref(void);
void ED_spacetype_clip(void);
+void ED_spacetype_collections(void);
/* calls for instancing and freeing spacetype static data
* called in WM_init_exit */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 3dc84dacbf9..f55d723968f 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -103,7 +103,7 @@ enum TfmMode {
#define CTX_GPENCIL_STROKES (1 << 9)
struct TransInfo;
-struct Base;
+struct BaseLegacy;
struct Scene;
struct Object;
struct wmOperator;
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 7944b434057..6eaae49912c 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -65,10 +65,6 @@ struct SnapObjectParams {
unsigned int use_object_edit_cage : 1;
};
-enum {
- SNAP_OBJECT_USE_CACHE = (1 << 0),
-};
-
typedef struct SnapObjectContext SnapObjectContext;
SnapObjectContext *ED_transform_snap_object_context_create(
struct Main *bmain, struct Scene *scene, int flag);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 79176d9e9cf..cc83b97fc00 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -37,7 +37,7 @@ struct BMEdge;
struct BMFace;
struct BMVert;
struct BPoint;
-struct Base;
+struct BaseLegacy;
struct BezTriple;
struct BoundBox;
struct EditBone;
@@ -49,6 +49,7 @@ struct Nurb;
struct Object;
struct RegionView3D;
struct Scene;
+struct SceneLayer;
struct ScrArea;
struct View3D;
struct ViewContext;
@@ -70,6 +71,7 @@ enum eGPUFXFlags;
/* for derivedmesh drawing callbacks, for view3d_select, .... */
typedef struct ViewContext {
struct Scene *scene;
+ struct SceneLayer *sl;
struct Object *obact;
struct Object *obedit;
struct ARegion *ar;
@@ -187,7 +189,7 @@ void pose_foreachScreenBone(
void ED_view3d_project_float_v2_m4(const struct ARegion *ar, const float co[3], float r_co[2], float mat[4][4]);
void ED_view3d_project_float_v3_m4(const struct ARegion *ar, const float co[3], float r_co[3], float mat[4][4]);
-eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base);
+eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct BaseLegacy *base);
/* *** short *** */
eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local,
@@ -277,6 +279,7 @@ float ED_view3d_radius_to_dist(
const float radius);
void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4]);
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos);
/* backbuffer select and draw support */
void ED_view3d_backbuf_validate(struct ViewContext *vc);
@@ -352,7 +355,7 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
int alpha_mode, int samples, bool full_samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
-struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
+struct BaseLegacy *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]);
bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index d48cfbee413..153c3d415e6 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -212,6 +212,9 @@ enum {
UI_BUT_ALIGN_STITCH_TOP = (1 << 18),
UI_BUT_ALIGN_STITCH_LEFT = (1 << 19),
UI_BUT_ALIGN_ALL = (UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT),
+
+ /* Another hack, in some rare cases we don't want any text margin */
+ UI_BUT_TEXT_NO_MARGIN = (1 << 20),
};
/* scale fixed button widths by this to account for DPI */
@@ -311,14 +314,14 @@ typedef enum {
void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad, const float color[4]);
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_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad, const float color[4]);
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
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_roundbox_shade_x(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown, const float col[4]);
+void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeleft, float shaderight, const float col[4]);
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]);
void UI_draw_safe_areas(
unsigned pos, float x1, float x2, float y1, float y2,
@@ -1044,12 +1047,14 @@ void UI_context_active_but_prop_get_templateID(
/* Styled text draw */
void UI_fontstyle_set(const struct uiFontStyle *fs);
-void UI_fontstyle_draw_ex(
- const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
- size_t len, float *r_xofs, float *r_yofs);
-void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str);
-void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str);
-void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str);
+void UI_fontstyle_draw_ex(const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
+ const unsigned char col[4], size_t len, float *r_xofs, float *r_yofs);
+void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
+ const unsigned char col[4]);
+void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
+ const unsigned char col[4]);
+void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str,
+ const unsigned char col[4]);
void UI_fontstyle_draw_simple_backdrop(
const struct uiFontStyle *fs, float x, float y, const char *str,
const float col_fg[4], const float col_bg[4]);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 945ac1b6db9..f08c46af8a6 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -83,5 +83,6 @@ struct PreviewImage *UI_icon_to_preview(int icon_id);
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
int UI_idcode_icon_get(const int idcode);
+int UI_colorset_icon_get(const int set_idx);
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index b7a5217a862..2fc76ae9563 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -347,6 +347,10 @@ void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigne
// get the color, range 0.0-1.0, complete with shading offset
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]);
void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]);
+void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4]);
+
+// get three color values, range 0-255, complete with shading offset for the RGB components and blending
+void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3]);
// get four color values, scaled to 0.0-1.0 range
void UI_GetThemeColor4fv(int colorid, float col[4]);
@@ -376,6 +380,10 @@ void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3]
// get a 3 byte color, blended and shaded between two other char color pointers
void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], float fac, int offset);
+// sets the font color
+// (for anything fancy use UI_GetThemeColor[Fancy] then BLF_color)
+void UI_FontThemeColor(int fontid, int colorid);
+
// clear the openGL ClearColor using the input colorid
void UI_ThemeClearColor(int colorid);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index f17c61b8aa1..7b17c3d6440 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -57,7 +57,9 @@
#include "GPU_draw.h"
#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "UI_interface.h"
@@ -114,9 +116,7 @@ void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, floa
mul_v2_fl(vec[a], rad);
}
- if (mode == GL_POLYGON) {
- mode = GL_TRIANGLE_FAN;
- }
+ BLI_assert(mode != GL_POLYGON);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(col);
@@ -174,245 +174,272 @@ void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, floa
immUnbindProgram();
}
-static void round_box_shade_col(const float col1[3], float const col2[3], const float fac)
+static void round_box_shade_col(unsigned attrib, const float col1[3], float const col2[3], const float fac)
{
- float col[3] = {
+ float col[4] = {
fac * col1[0] + (1.0f - fac) * col2[0],
fac * col1[1] + (1.0f - fac) * col2[1],
- fac * col1[2] + (1.0f - fac) * col2[2]
+ fac * col1[2] + (1.0f - fac) * col2[2],
+ 1.0f
};
- glColor3fv(col);
+ immAttrib4fv(attrib, col);
}
/* linear horizontal shade within button or in outline */
/* view2d scrollers use it */
void UI_draw_roundbox_shade_x(
int mode, float minx, float miny, float maxx, float maxy,
- float rad, float shadetop, float shadedown)
+ float rad, float shadetop, float shadedown, const 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}};
const float div = maxy - miny;
const float idiv = 1.0f / div;
- float coltop[3], coldown[3], color[4];
+ float coltop[3], coldown[3];
+ int vert_count = 0;
int a;
-
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
}
- /* get current color, needs to be outside of glBegin/End */
- glGetFloatv(GL_CURRENT_COLOR, color);
+
+ BLI_assert(mode != GL_POLYGON);
/* 'shade' defines strength of shading */
- coltop[0] = min_ff(1.0f, color[0] + shadetop);
- coltop[1] = min_ff(1.0f, color[1] + shadetop);
- coltop[2] = min_ff(1.0f, color[2] + shadetop);
- coldown[0] = max_ff(0.0f, color[0] + shadedown);
- coldown[1] = max_ff(0.0f, color[1] + shadedown);
- coldown[2] = max_ff(0.0f, color[2] + shadedown);
+ coltop[0] = min_ff(1.0f, col[0] + shadetop);
+ coltop[1] = min_ff(1.0f, col[1] + shadetop);
+ coltop[2] = min_ff(1.0f, col[2] + shadetop);
+ coldown[0] = max_ff(0.0f, col[0] + shadedown);
+ coldown[1] = max_ff(0.0f, col[1] + shadedown);
+ coldown[2] = max_ff(0.0f, col[2] + shadedown);
- glBegin(mode);
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
+
+ immBegin(mode, vert_count);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(maxx - rad, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, vec[a][1] * idiv);
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- round_box_shade_col(coltop, coldown, rad * idiv);
- glVertex2f(maxx, miny + rad);
+ round_box_shade_col(color, coltop, coldown, rad * idiv);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(maxx, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, maxx, miny);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- round_box_shade_col(coltop, coldown, (div - rad) * idiv);
- glVertex2f(maxx, maxy - rad);
+ round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, (div - rad + vec[a][1]) * idiv);
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(maxx - rad, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(maxx, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(minx + rad, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, (div - vec[a][1]) * idiv);
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- round_box_shade_col(coltop, coldown, (div - rad) * idiv);
- glVertex2f(minx, maxy - rad);
+ round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- round_box_shade_col(coltop, coldown, 1.0);
- glVertex2f(minx, maxy);
+ round_box_shade_col(color, coltop, coldown, 1.0);
+ immVertex2f(pos, minx, maxy);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- round_box_shade_col(coltop, coldown, rad * idiv);
- glVertex2f(minx, miny + rad);
+ round_box_shade_col(color, coltop, coldown, rad * idiv);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(coltop, coldown, (rad - vec[a][1]) * idiv);
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(minx + rad, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- round_box_shade_col(coltop, coldown, 0.0);
- glVertex2f(minx, miny);
+ round_box_shade_col(color, coltop, coldown, 0.0);
+ immVertex2f(pos, minx, miny);
}
-
- glEnd();
+
+ immEnd();
+ immUnbindProgram();
}
/* linear vertical shade within button or in outline */
/* view2d scrollers use it */
void UI_draw_roundbox_shade_y(
int mode, float minx, float miny, float maxx, float maxy,
- float rad, float shadeLeft, float shadeRight)
+ float rad, float shadeleft, float shaderight, const 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}};
const float div = maxx - minx;
const float idiv = 1.0f / div;
- float colLeft[3], colRight[3], color[4];
+ float colLeft[3], colRight[3];
+ int vert_count = 0;
int a;
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
}
- /* get current color, needs to be outside of glBegin/End */
- glGetFloatv(GL_CURRENT_COLOR, color);
+
+ BLI_assert(mode != GL_POLYGON);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* 'shade' defines strength of shading */
- colLeft[0] = min_ff(1.0f, color[0] + shadeLeft);
- colLeft[1] = min_ff(1.0f, color[1] + shadeLeft);
- colLeft[2] = min_ff(1.0f, color[2] + shadeLeft);
- colRight[0] = max_ff(0.0f, color[0] + shadeRight);
- colRight[1] = max_ff(0.0f, color[1] + shadeRight);
- colRight[2] = max_ff(0.0f, color[2] + shadeRight);
+ colLeft[0] = min_ff(1.0f, col[0] + shadeleft);
+ colLeft[1] = min_ff(1.0f, col[1] + shadeleft);
+ colLeft[2] = min_ff(1.0f, col[2] + shadeleft);
+ colRight[0] = max_ff(0.0f, col[0] + shaderight);
+ colRight[1] = max_ff(0.0f, col[1] + shaderight);
+ colRight[2] = max_ff(0.0f, col[2] + shaderight);
+
+
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
- glBegin(mode);
+ immBegin(mode, vert_count);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx - rad, miny);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, vec[a][0] * idiv);
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- round_box_shade_col(colLeft, colRight, rad * idiv);
- glVertex2f(maxx, miny + rad);
+ round_box_shade_col(color, colLeft, colRight, rad * idiv);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx, miny);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, miny);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx, maxy - rad);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, (div - rad - vec[a][0]) * idiv);
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- round_box_shade_col(colLeft, colRight, (div - rad) * idiv);
- glVertex2f(maxx - rad, maxy);
+ round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- round_box_shade_col(colLeft, colRight, 0.0);
- glVertex2f(maxx, maxy);
+ round_box_shade_col(color, colLeft, colRight, 0.0);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- round_box_shade_col(colLeft, colRight, (div - rad) * idiv);
- glVertex2f(minx + rad, maxy);
+ round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, (div - rad + vec[a][0]) * idiv);
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, maxy - rad);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, maxy);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, maxy);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, miny + rad);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 7; a++) {
- round_box_shade_col(colLeft, colRight, (vec[a][0]) * idiv);
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx + rad, miny);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- round_box_shade_col(colLeft, colRight, 1.0);
- glVertex2f(minx, miny);
+ round_box_shade_col(color, colLeft, colRight, 1.0);
+ immVertex2f(pos, minx, miny);
}
-
- glEnd();
+
+ immEnd();
+ immUnbindProgram();
}
/* plain antialiased unfilled rectangle */
-void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad, const float color[4])
{
- float color[4];
-
+ float col[4];
+
+ copy_v4_v4(col, color);
+
if (roundboxtype & UI_RB_ALPHA) {
- glGetFloatv(GL_CURRENT_COLOR, color);
- color[3] = 0.5;
- glColor4fv(color);
- glEnable(GL_BLEND);
+ col[3] = 0.5;
}
/* set antialias line */
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad, color);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad, col);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -421,13 +448,21 @@ void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, f
/* (old, used in outliner) plain antialiased filled box */
void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad, const float color[4])
{
- ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA, color);
+ ui_draw_anti_roundbox(GL_TRIANGLE_FAN, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA, color);
}
-void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4])
{
int ofs_y = 4 * U.pixelsize;
- glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
+
+ 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, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
+ immUnbindProgram();
}
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
@@ -457,7 +492,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
#endif
glEnable(GL_BLEND);
- glColor4f(0.0, 0.0, 0.0, 0.0);
+ glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
if (w != ibuf->x || h != ibuf->y) {
float facx = (float)w / (float)ibuf->x;
@@ -531,45 +566,53 @@ static void draw_scope_end(const rctf *rect, GLint *scissor)
static void histogram_draw_one(
float r, float g, float b, float alpha,
- float x, float y, float w, float h, const float *data, int res, const bool is_line)
+ float x, float y, float w, float h, const float *data, int res, const bool is_line,
+ unsigned int pos_attrib)
{
+ float color[4] = {r, g, b, alpha};
+
+ /* that can happen */
+ if (res == 0)
+ return;
+
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glColor4f(r, g, b, alpha);
+
+ immUniformColor4fv(color);
if (is_line) {
/* curve outline */
glLineWidth(1.5);
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
- glVertex2f(x2, y + (data[i] * h));
+ immVertex2f(pos_attrib, x2, y + (data[i] * h));
}
- glEnd();
+ immEnd();
}
else {
/* under the curve */
- glBegin(GL_TRIANGLE_STRIP);
- glVertex2f(x, y);
- glVertex2f(x, y + (data[0] * h));
+ immBegin(GL_TRIANGLE_STRIP, res * 2);
+ immVertex2f(pos_attrib, x, y);
+ immVertex2f(pos_attrib, x, y + (data[0] * h));
for (int i = 1; i < res; i++) {
float x2 = x + i * (w / (float)res);
- glVertex2f(x2, y + (data[i] * h));
- glVertex2f(x2, y);
+ immVertex2f(pos_attrib, x2, y + (data[i] * h));
+ immVertex2f(pos_attrib, x2, y);
}
- glEnd();
+ immEnd();
/* curve outline */
- glColor4f(0.f, 0.f, 0.f, 0.25f);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, res);
for (int i = 0; i < res; i++) {
float x2 = x + i * (w / (float)res);
- glVertex2f(x2, y + (data[i] * h));
+ immVertex2f(pos_attrib, x2, y + (data[i] * h));
}
- glEnd();
+ immEnd();
}
glDisable(GL_LINE_SMOOTH);
@@ -582,7 +625,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
Histogram *hist = (Histogram *)but->poin;
int res = hist->x_resolution;
const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0;
-
+
rctf rect = {
.xmin = (float)recti->xmin + 1,
.xmax = (float)recti->xmax - 1,
@@ -599,7 +642,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, 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];
@@ -609,34 +652,41 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
- glColor4f(1.f, 1.f, 1.f, 0.08f);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
/* draw grid lines here */
for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) {
const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES;
/* so we can tell the 1.0 color point */
if (i == HISTOGRAM_TOT_GRID_LINES) {
- glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}
- fdrawline(rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h);
- fdrawline(rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax);
+ imm_draw_line(pos, rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h);
+ imm_draw_line(pos, rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax);
}
-
+
if (hist->mode == HISTO_MODE_LUMA) {
- histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line);
+ histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos);
}
else if (hist->mode == HISTO_MODE_ALPHA) {
- histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line);
+ histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos);
}
else {
if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R)
- histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line);
+ histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos);
if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G)
- histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line);
+ histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos);
if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B)
- histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line);
+ histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos);
}
+
+ immUnbindProgram();
/* outline */
draw_scope_end(&rect, scissor);
@@ -644,6 +694,25 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
#undef HISTOGRAM_TOT_GRID_LINES
+static void waveform_draw_one(float *waveform, int nbr, const float col[3])
+{
+ VertexFormat format = {0};
+ unsigned int pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, nbr);
+
+ fillAttrib(vbo, pos_id, waveform);
+
+ /* TODO store the Batch inside the scope */
+ Batch *batch = Batch_create(GL_POINTS, vbo, NULL);
+ Batch_set_builtin_program(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ Batch_Uniform4f(batch, "color", col[0], col[1], col[2], 1.0f);
+ Batch_draw(batch);
+
+ Batch_discard_all(batch);
+}
+
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
Scopes *scopes = (Scopes *)but->poin;
@@ -666,7 +735,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
scopes->wavefrm_yfac = 0.98f;
float w = BLI_rctf_size_x(&rect) - 7;
float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
- float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f;
+ float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f;
float w3 = w / 3.0f;
/* log scale for alpha */
@@ -687,7 +756,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, 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);
@@ -696,94 +765,85 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
- glColor4f(1.f, 1.f, 1.f, 0.08f);
- /* draw grid lines here */
+ /* draw scale numbers first before binding any shader */
for (int i = 0; i < 6; i++) {
char str[4];
BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
str[3] = '\0';
- fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h);
- BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1);
- /* in the loop because blf_draw reset it */
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f);
+ BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1);
+ }
+
+ 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);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
+ /* draw grid lines here */
+ for (int i = 0; i < 6; i++) {
+ imm_draw_line(pos, rect.xmin + 22, yofs + (i * 0.2f) * h, rect.xmax + 1, yofs + (i * 0.2f) * h);
}
/* 3 vertical separation */
if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
for (int i = 1; i < 3; i++) {
- fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax);
+ imm_draw_line(pos, rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax);
}
}
/* separate min max zone on the right */
- fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax);
+ imm_draw_line(pos, rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax);
/* 16-235-240 level in case of ITU-R BT601/709 */
- glColor4f(1.f, 0.4f, 0.f, 0.2f);
+ immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
- fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
- fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
- fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
- fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
+ imm_draw_line(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
+ imm_draw_line(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
+ imm_draw_line(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
+ imm_draw_line(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
}
/* 7.5 IRE black point level for NTSC */
if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA)
- fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f);
+ imm_draw_line(pos, rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f);
if (scopes->ok && scopes->waveform_1 != NULL) {
-
- /* LUMA (1 channel) */
+ gpuMatrixBegin3D_legacy();
glBlendFunc(GL_ONE, GL_ONE);
- glColor3f(alpha, alpha, alpha);
glPointSize(1.0);
+ /* LUMA (1 channel) */
if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
+ float col[3] = {alpha, alpha, alpha};
- glBlendFunc(GL_ONE, GL_ONE);
-
- glPushMatrix();
- glEnableClientState(GL_VERTEX_ARRAY);
-
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w, h, 0.f);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ gpuPushMatrix();
+ gpuTranslate3f(rect.xmin, yofs, 0.0f);
+ gpuScale3f(w, h, 0.0f);
+
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
/* min max */
- glColor3f(0.5f, 0.5f, 0.5f);
+ immUniformColor3f(0.5f, 0.5f, 0.5f);
min = yofs + scopes->minmax[0][0] * h;
max = yofs + scopes->minmax[0][1] * h;
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- fdrawline(rect.xmax - 3, min, rect.xmax - 3, max);
+ imm_draw_line(pos, rect.xmax - 3, min, rect.xmax - 3, max);
}
/* RGB (3 channel) */
else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
- glBlendFunc(GL_ONE, GL_ONE);
-
- glEnableClientState(GL_VERTEX_ARRAY);
-
- glPushMatrix();
-
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w, h, 0.f);
+ gpuPushMatrix();
+ gpuTranslate3f(rect.xmin, yofs, 0.0f);
+ gpuScale3f(w, h, 0.0f);
- glColor3fv( colors_alpha[0] );
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
+ waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
+ waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
- glColor3fv( colors_alpha[1] );
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- glColor3fv( colors_alpha[2] );
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
}
/* PARADE / YCC (3 channels) */
else if (ELEM(scopes->wavefrm_mode,
@@ -795,49 +855,44 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
{
int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
- glBlendFunc(GL_ONE, GL_ONE);
-
- glPushMatrix();
- glEnableClientState(GL_VERTEX_ARRAY);
-
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w3, h, 0.f);
+ gpuPushMatrix();
+ gpuTranslate3f(rect.xmin, yofs, 0.0f);
+ gpuScale3f(w3, h, 0.0f);
- glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- glTranslatef(1.f, 0.f, 0.f);
- glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ gpuTranslate3f(1.0f, 0.0f, 0.0f);
+ waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
- glTranslatef(1.f, 0.f, 0.f);
- glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ gpuTranslate3f(1.0f, 0.0f, 0.0f);
+ waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
}
+
/* min max */
if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) {
for (int c = 0; c < 3; c++) {
if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB))
- glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
+ immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
else
- glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
+ immUniformColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
min = yofs + scopes->minmax[c][0] * h;
max = yofs + scopes->minmax[c][1] * h;
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max);
+ imm_draw_line(pos, rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max);
}
}
+ gpuMatrixEnd();
}
-
+
+ immUnbindProgram();
+
/* outline */
draw_scope_end(&rect, scissor);
+
+ glDisable(GL_BLEND);
}
static float polar_to_x(float center, float diam, float ampli, float angle)
@@ -850,10 +905,10 @@ static float polar_to_y(float center, float diam, float ampli, float angle)
return center + diam * ampli * sinf(angle);
}
-static void vectorscope_draw_target(float centerx, float centery, float diam, const float colf[3])
+static void vectorscope_draw_target(unsigned int pos, float centerx, float centery, float diam, const float colf[3])
{
float y, u, v;
- float tangle = 0.f, tampli;
+ float tangle = 0.0f, tampli;
float dangle, dampli, dangle2, dampli2;
rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v);
@@ -865,41 +920,41 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co
tampli = sqrtf(u * u + v * v);
/* small target vary by 2.5 degree and 2.5 IRE unit */
- glColor4f(1.0f, 1.0f, 1.0, 0.12f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
dangle = DEG2RADF(2.5f);
dampli = 2.5f / 200.0f;
- glBegin(GL_LINE_LOOP);
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
- glEnd();
+ immBegin(GL_LINE_LOOP, 4);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
+ immEnd();
/* big target vary by 10 degree and 20% amplitude */
- glColor4f(1.0f, 1.0f, 1.0, 0.12f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
dangle = DEG2RADF(10.0f);
dampli = 0.2f * tampli;
dangle2 = DEG2RADF(5.0f);
dampli2 = 0.5f * dampli;
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
- glEnd();
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
- glEnd();
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
- glEnd();
- glBegin(GL_LINE_STRIP);
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
- glVertex2f(polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
- glEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
+ immEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
+ immEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
+ immEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
+ immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
+ immEnd();
}
void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
@@ -920,8 +975,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
float w = BLI_rctf_size_x(&rect);
float h = BLI_rctf_size_y(&rect);
- float centerx = rect.xmin + w / 2;
- float centery = rect.ymin + h / 2;
+ float centerx = rect.xmin + w * 0.5f;
+ float centery = rect.ymin + h * 0.5f;
float diam = (w < h) ? w : h;
float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
@@ -932,7 +987,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, 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];
@@ -942,93 +997,99 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
(rect.xmax + 1) - (rect.xmin - 1),
(rect.ymax + 1) - (rect.ymin - 1));
- glColor4f(1.f, 1.f, 1.f, 0.08f);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
/* draw grid elements */
/* cross */
- fdrawline(centerx - (diam / 2) - 5, centery, centerx + (diam / 2) + 5, centery);
- fdrawline(centerx, centery - (diam / 2) - 5, centerx, centery + (diam / 2) + 5);
+ imm_draw_line(pos, centerx - (diam * 0.5f) - 5, centery, centerx + (diam * 0.5f) + 5, centery);
+ imm_draw_line(pos, centerx, centery - (diam * 0.5f) - 5, centerx, centery + (diam * 0.5f) + 5);
/* circles */
for (int j = 0; j < 5; j++) {
- glBegin(GL_LINE_LOOP);
const int increment = 15;
+ immBegin(GL_LINE_LOOP, (int)(360 / increment));
for (int i = 0; i <= 360 - increment; i += increment) {
const float a = DEG2RADF((float)i);
- const float r = (j + 1) / 10.0f;
- glVertex2f(polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
+ const float r = (j + 1) * 0.1f;
+ immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
}
- glEnd();
+ immEnd();
}
/* skin tone line */
- glColor4f(1.f, 0.4f, 0.f, 0.2f);
- fdrawline(polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5, skin_rad),
- polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1, skin_rad));
+ immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
+ imm_draw_line(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad),
+ polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
/* saturation points */
for (int i = 0; i < 6; i++)
- vectorscope_draw_target(centerx, centery, diam, colors[i]);
+ vectorscope_draw_target(pos, centerx, centery, diam, colors[i]);
if (scopes->ok && scopes->vecscope != NULL) {
/* pixel point cloud */
+ float col[3] = {alpha, alpha, alpha};
+
glBlendFunc(GL_ONE, GL_ONE);
- glColor3f(alpha, alpha, alpha);
+ glPointSize(1.0);
- glPushMatrix();
- glEnableClientState(GL_VERTEX_ARRAY);
+ gpuMatrixBegin3D_legacy();
+ gpuPushMatrix();
+ gpuTranslate3f(centerx, centery, 0.0f);
+ gpuScale3f(diam, diam, 0.0f);
- glTranslatef(centerx, centery, 0.f);
- glScalef(diam, diam, 0.f);
+ waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
- glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope);
- glPointSize(1.0);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ gpuPopMatrix();
+ gpuMatrixEnd();
}
+ immUnbindProgram();
+
/* outline */
draw_scope_end(&rect, scissor);
glDisable(GL_BLEND);
}
-static void ui_draw_colorband_handle_tri_hlight(float x1, float y1, float halfwidth, float height)
+static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, float y1, float halfwidth, float height)
{
glEnable(GL_LINE_SMOOTH);
- glBegin(GL_LINE_STRIP);
- glVertex2f(x1 + halfwidth, y1);
- glVertex2f(x1, y1 + height);
- glVertex2f(x1 - halfwidth, y1);
- glEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, x1 + halfwidth, y1);
+ immVertex2f(pos, x1, y1 + height);
+ immVertex2f(pos, x1 - halfwidth, y1);
+ immEnd();
glDisable(GL_LINE_SMOOTH);
}
-static void ui_draw_colorband_handle_tri(float x1, float y1, float halfwidth, float height, bool fill)
+static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, float halfwidth, float height, bool fill)
{
glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
- glBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP);
- glVertex2f(x1 + halfwidth, y1);
- glVertex2f(x1, y1 + height);
- glVertex2f(x1 - halfwidth, y1);
- glEnd();
+ immBegin(fill ? GL_TRIANGLES : GL_LINE_LOOP, 3);
+ immVertex2f(pos, x1 + halfwidth, y1);
+ immVertex2f(pos, x1, y1 + height);
+ immVertex2f(pos, x1 - halfwidth, y1);
+ immEnd();
glDisable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
}
-static void ui_draw_colorband_handle_box(float x1, float y1, float x2, float y2, bool fill)
+static void ui_draw_colorband_handle_box(unsigned int pos, float x1, float y1, float x2, float y2, bool fill)
{
- glBegin(fill ? GL_QUADS : GL_LINE_LOOP);
- glVertex2f(x1, y1);
- glVertex2f(x1, y2);
- glVertex2f(x2, y2);
- glVertex2f(x2, y1);
- glEnd();
+ immBegin(fill ? GL_QUADS : GL_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immEnd();
}
static void ui_draw_colorband_handle(
- const rcti *rect, float x,
+ unsigned int pos, const rcti *rect, float x,
const float rgb[3], struct ColorManagedDisplay *display,
bool active)
{
@@ -1047,17 +1108,18 @@ static void ui_draw_colorband_handle(
y1 = floorf(y1 + 0.5f);
if (active || half_width < min_width) {
- glBegin(GL_LINES);
- glColor3ub(0, 0, 0);
- glVertex2f(x, y1);
- glVertex2f(x, y2);
- glEnd();
+ immUniformColor3ub(0, 0, 0);
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, x, y1);
+ immVertex2f(pos, x, y2);
+ immEnd();
+
setlinestyle(active ? 2 : 1);
- glBegin(GL_LINES);
- glColor3ub(200, 200, 200);
- glVertex2f(x, y1);
- glVertex2f(x, y2);
- glEnd();
+ immUniformColor3ub(200, 200, 200);
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, x, y1);
+ immVertex2f(pos, x, y2);
+ immEnd();
setlinestyle(0);
/* hide handles when zoomed out too far */
@@ -1069,45 +1131,46 @@ static void ui_draw_colorband_handle(
/* shift handle down */
y1 -= half_width;
- glColor3ub(0, 0, 0);
- ui_draw_colorband_handle_box(x - half_width, y1 - 1, x + half_width, y1 + height, false);
+ immUniformColor3ub(0, 0, 0);
+ ui_draw_colorband_handle_box(pos, x - half_width, y1 - 1, x + half_width, y1 + height, false);
/* draw all triangles blended */
glEnable(GL_BLEND);
- ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
+ ui_draw_colorband_handle_tri(pos, x, y1 + height, half_width, half_width, true);
if (active)
- glColor3ub(196, 196, 196);
+ immUniformColor3ub(196, 196, 196);
else
- glColor3ub(96, 96, 96);
- ui_draw_colorband_handle_tri(x, y1 + height, half_width, half_width, true);
+ immUniformColor3ub(96, 96, 96);
+ ui_draw_colorband_handle_tri(pos, x, y1 + height, half_width, half_width, true);
if (active)
- glColor3ub(255, 255, 255);
+ immUniformColor3ub(255, 255, 255);
else
- glColor3ub(128, 128, 128);
- ui_draw_colorband_handle_tri_hlight(x, y1 + height - 1, (half_width - 1), (half_width - 1));
+ immUniformColor3ub(128, 128, 128);
+ ui_draw_colorband_handle_tri_hlight(pos, x, y1 + height - 1, (half_width - 1), (half_width - 1));
- glColor3ub(0, 0, 0);
- ui_draw_colorband_handle_tri_hlight(x, y1 + height, half_width, half_width);
+ immUniformColor3ub(0, 0, 0);
+ ui_draw_colorband_handle_tri_hlight(pos, x, y1 + height, half_width, half_width);
glDisable(GL_BLEND);
- glColor3ub(128, 128, 128);
- ui_draw_colorband_handle_box(x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
+ immUniformColor3ub(128, 128, 128);
+ ui_draw_colorband_handle_box(pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
if (display) {
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
}
- glColor3fv(colf);
- ui_draw_colorband_handle_box(x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
+ immUniformColor3fv(colf);
+ ui_draw_colorband_handle_box(pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
}
void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
struct ColorManagedDisplay *display = NULL;
+ unsigned int position, color;
ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
if (coba == NULL) return;
@@ -1118,20 +1181,25 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
float x1 = rect->xmin;
float sizex = rect->xmax - x1;
float sizey = BLI_rcti_size_y(rect);
- float sizey_solid = sizey / 4;
+ float sizey_solid = sizey * 0.25f;
float y1 = rect->ymin;
- /* Drawing the checkerboard.
- * This could be optimized with a single checkerboard shader,
- * instead of drawing twice and using stippling the second time. */
- /* layer: background, to show tranparency */
- glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
- glRectf(x1, y1, x1 + sizex, rect->ymax);
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX);
- glRectf(x1, y1, x1 + sizex, rect->ymax);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ VertexFormat *format = immVertexFormat();
+ position = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
+
+ /* Drawing the checkerboard. */
+ immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f);
+ immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f);
+ immUniform1i("size", 8);
+ immRectf(position, x1, y1, x1 + sizex, rect->ymax);
+ immUnbindProgram();
+
+ /* New format */
+ format = immVertexFormat();
+ position = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ color = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* layer: color ramp */
glEnable(GL_BLEND);
@@ -1144,7 +1212,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1 + sizey_solid;
v2[1] = rect->ymax;
- glBegin(GL_TRIANGLE_STRIP);
+ immBegin(GL_TRIANGLE_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
do_colorband(coba, pos, colf);
@@ -1153,17 +1221,17 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[0] = v2[0] = x1 + a;
- glColor4fv(colf);
- glVertex2fv(v1);
- glVertex2fv(v2);
+ immAttrib4fv(color, colf);
+ immVertex2fv(position, v1);
+ immVertex2fv(position, v2);
}
- glEnd();
+ immEnd();
/* layer: color ramp without alpha for reference when manipulating ramp properties */
v1[1] = y1;
v2[1] = y1 + sizey_solid;
- glBegin(GL_TRIANGLE_STRIP);
+ immBegin(GL_TRIANGLE_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
do_colorband(coba, pos, colf);
@@ -1172,31 +1240,38 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[0] = v2[0] = x1 + a;
- glColor4f(colf[0], colf[1], colf[2], 1.0f);
- glVertex2fv(v1);
- glVertex2fv(v2);
+ immAttrib4f(color, colf[0], colf[1], colf[2], 1.0f);
+ immVertex2fv(position, v1);
+ immVertex2fv(position, v2);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
glDisable(GL_BLEND);
+ /* New format */
+ format = immVertexFormat();
+ position = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* layer: box outline */
- glColor4f(0.0, 0.0, 0.0, 1.0);
- fdrawbox(x1, y1, x1 + sizex, rect->ymax);
-
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ imm_draw_line_box(position, x1, y1, x1 + sizex, rect->ymax);
+
/* layer: box outline */
glEnable(GL_BLEND);
- glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- fdrawline(x1, y1, x1 + sizex, y1);
- glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
- fdrawline(x1, y1 - 1, x1 + sizex, y1 - 1);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ imm_draw_line(position, x1, y1, x1 + sizex, y1);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
+ imm_draw_line(position, x1, y1 - 1, x1 + sizex, y1 - 1);
glDisable(GL_BLEND);
/* layer: draw handles */
for (int a = 0; a < coba->tot; a++, cbd++) {
if (a != coba->cur) {
float pos = x1 + cbd->pos * (sizex - 1) + 1;
- ui_draw_colorband_handle(rect, pos, &cbd->r, display, false);
+ ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, false);
}
}
@@ -1204,116 +1279,103 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
if (coba->tot != 0) {
cbd = &coba->data[coba->cur];
float pos = x1 + cbd->pos * (sizex - 1) + 1;
- ui_draw_colorband_handle(rect, pos, &cbd->r, display, true);
+ ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, true);
}
+
+ immUnbindProgram();
}
void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
- static GLuint displist = 0;
+ /* sphere color */
float diffuse[3] = {1.0f, 1.0f, 1.0f};
+ float light[3];
float size;
/* backdrop */
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode_3ubAlpha(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255);
+ UI_draw_roundbox_gl_mode_3ubAlpha(GL_TRIANGLE_FAN, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255);
- /* sphere color */
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
/* setup lights */
- GPULightData light = {0};
- light.type = GPU_LIGHT_SUN;
- copy_v3_v3(light.diffuse, diffuse);
- zero_v3(light.specular);
- ui_but_v3_get(but, light.direction);
-
- GPU_basic_shader_light_set(0, &light);
- for (int a = 1; a < 8; a++)
- GPU_basic_shader_light_set(a, NULL);
-
- /* setup shader */
- GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
+ ui_but_v3_get(but, light);
+ light[2] = -light[2];
/* transform to button */
- glPushMatrix();
- glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f);
+ gpuMatrixBegin3D_legacy();
+ gpuPushMatrix();
if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
- size = BLI_rcti_size_x(rect) / 200.f;
+ size = 0.5f * BLI_rcti_size_x(rect);
else
- size = BLI_rcti_size_y(rect) / 200.f;
-
- glScalef(size, size, MIN2(size, 1.0f));
-
- if (displist == 0) {
- GLUquadricObj *qobj;
+ size = 0.5f * BLI_rcti_size_y(rect);
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
- GPU_basic_shader_bind(GPU_basic_shader_bound_options());
- gluSphere(qobj, 100.0, 32, 24);
- gluDeleteQuadric(qobj);
-
- glEndList();
- }
+ gpuTranslate3f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f);
+ gpuScale3f(size, size, size);
- glCallList(displist);
+ Batch *sphere = Batch_get_sphere(2);
+ Batch_set_builtin_program(sphere, GPU_SHADER_SIMPLE_LIGHTING);
+ Batch_Uniform4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
+ Batch_Uniform3fv(sphere, "light", light);
+ Batch_draw(sphere);
/* restore */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- GPU_default_lights();
glDisable(GL_CULL_FACE);
/* AA circle */
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv((unsigned char *)wcol->inner);
+
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glColor3ubv((unsigned char *)wcol->inner);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, 100.0f, 32);
+ imm_draw_lined_circle(pos, 0.0f, 0.0f, 1.0f, 32);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
/* matrix after circle */
- glPopMatrix();
+ gpuPopMatrix();
+ gpuMatrixEnd();
- /* We disabled all blender lights above, so restore them here. */
- GPU_default_lights();
+ immUnbindProgram();
}
-static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
+static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
{
- glBegin(GL_LINES);
float dx = step * zoomx;
float fx = rect->xmin + zoomx * (-offsx);
if (fx > rect->xmin) fx -= dx * (floorf(fx - rect->xmin));
- while (fx < rect->xmax) {
- glVertex2f(fx, rect->ymin);
- glVertex2f(fx, rect->ymax);
- fx += dx;
- }
float dy = step * zoomy;
float fy = rect->ymin + zoomy * (-offsy);
if (fy > rect->ymin) fy -= dy * (floorf(fy - rect->ymin));
+
+ float line_count = floorf((rect->xmax - fx) / dx) + 1.0f +
+ floorf((rect->ymax - fy) / dy) + 1.0f;
+
+ immBegin(GL_LINES, (int)line_count * 2);
+ while (fx < rect->xmax) {
+ immVertex2f(pos, fx, rect->ymin);
+ immVertex2f(pos, fx, rect->ymax);
+ fx += dx;
+ }
while (fy < rect->ymax) {
- glVertex2f(rect->xmin, fy);
- glVertex2f(rect->xmax, fy);
+ immVertex2f(pos, rect->xmin, fy);
+ immVertex2f(pos, rect->xmax, fy);
fy += dy;
}
- glEnd();
+ immEnd();
}
static void gl_shaded_color(unsigned char *col, int shade)
{
- glColor3ub(col[0] - shade > 0 ? col[0] - shade : 0,
- col[1] - shade > 0 ? col[1] - shade : 0,
- col[2] - shade > 0 ? col[2] - shade : 0);
+ immUniformColor3ub(col[0] - shade > 0 ? col[0] - shade : 0,
+ col[1] - shade > 0 ? col[1] - shade : 0,
+ col[2] - shade > 0 ? col[2] - shade : 0);
}
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect)
@@ -1349,10 +1411,8 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr);
float offsx = cumap->curr.xmin - (1.0f / zoomx);
float offsy = cumap->curr.ymin - (1.0f / zoomy);
-
- glLineWidth(1.0f);
- /* backdrop */
+ /* Do this first to not mess imm context */
if (but->a1 == UI_GRAD_H) {
/* magic trigger for curve backgrounds */
float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */
@@ -1365,96 +1425,105 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
};
ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
+ }
+ glLineWidth(1.0f);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* backdrop */
+ if (but->a1 == UI_GRAD_H) {
/* grid, hsv uses different grid */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4ub(0, 0, 0, 48);
- ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
+ immUniformColor4ub(0, 0, 0, 48);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
glDisable(GL_BLEND);
}
else {
if (cumap->flag & CUMA_DO_CLIP) {
gl_shaded_color((unsigned char *)wcol->inner, -20);
- glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- glColor3ubv((unsigned char *)wcol->inner);
- glRectf(rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
- rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
- rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
- rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ubv((unsigned char *)wcol->inner);
+ immRectf(pos, rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
+ rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
+ rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
+ rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
}
else {
- glColor3ubv((unsigned char *)wcol->inner);
- glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ubv((unsigned char *)wcol->inner);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
/* grid, every 0.25 step */
gl_shaded_color((unsigned char *)wcol->inner, -16);
- ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 0.25f);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
/* grid, every 1.0 step */
gl_shaded_color((unsigned char *)wcol->inner, -24);
- ui_draw_but_curve_grid(rect, zoomx, zoomy, offsx, offsy, 1.0f);
+ ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
/* axes */
gl_shaded_color((unsigned char *)wcol->inner, -50);
- glBegin(GL_LINES);
- glVertex2f(rect->xmin, rect->ymin + zoomy * (-offsy));
- glVertex2f(rect->xmax, rect->ymin + zoomy * (-offsy));
- glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (-offsx), rect->ymax);
- glEnd();
+ immBegin(GL_LINES, 4);
+ immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy));
+ immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy));
+ immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax);
+ immEnd();
}
/* cfra option */
/* XXX 2.48 */
#if 0
if (cumap->flag & CUMA_DRAW_CFRA) {
- glColor3ub(0x60, 0xc0, 0x40);
- glBegin(GL_LINES);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
- glEnd();
+ immUniformColor3ub(0x60, 0xc0, 0x40);
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
+ immEnd();
}
#endif
/* sample option */
if (cumap->flag & CUMA_DRAW_SAMPLE) {
- glBegin(GL_LINES); /* will draw one of the following 3 lines */
+ immBegin(GL_LINES, 2); /* will draw one of the following 3 lines */
if (but->a1 == UI_GRAD_H) {
float tsample[3];
float hsv[3];
linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
rgb_to_hsv_v(tsample, hsv);
- glColor3ub(240, 240, 240);
+ immUniformColor3ub(240, 240, 240);
- glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
+ immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
}
else if (cumap->cur == 3) {
float lum = IMB_colormanagement_get_luminance(cumap->sample);
- glColor3ub(240, 240, 240);
+ immUniformColor3ub(240, 240, 240);
- glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (lum - offsx), rect->ymax);
+ immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax);
}
else {
if (cumap->cur == 0)
- glColor3ub(240, 100, 100);
+ immUniformColor3ub(240, 100, 100);
else if (cumap->cur == 1)
- glColor3ub(100, 240, 100);
+ immUniformColor3ub(100, 240, 100);
else
- glColor3ub(100, 100, 240);
+ immUniformColor3ub(100, 100, 240);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
- glVertex2f(rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
+ immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
}
- glEnd();
+ immEnd();
}
/* the curve */
- glColor3ubv((unsigned char *)wcol->item);
+ immUniformColor3ubv((unsigned char *)wcol->item);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, (CM_TABLE+1) + 2);
if (cuma->table == NULL)
curvemapping_changed(cumap, false);
@@ -1463,52 +1532,67 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti
/* first point */
if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
- glVertex2f(rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy));
+ immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy));
}
else {
float fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
float fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
- glVertex2f(fx, fy);
+ immVertex2f(pos, fx, fy);
}
for (int a = 0; a <= CM_TABLE; a++) {
float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
- glVertex2f(fx, fy);
+ immVertex2f(pos, fx, fy);
}
/* last point */
if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
- glVertex2f(rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy));
+ immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy));
}
else {
float fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
float fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
- glVertex2f(fx, fy);
+ immVertex2f(pos, fx, fy);
}
- glEnd();
+ immEnd();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
+ immUnbindProgram();
/* the points, use aspect to make them visible on edges */
+ format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
cmp = cuma->curve;
glPointSize(3.0f);
- glBegin(GL_POINTS);
+ immBegin(GL_POINTS, cuma->totpoint);
for (int a = 0; a < cuma->totpoint; a++) {
+ float color[4];
if (cmp[a].flag & CUMA_SELECT)
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4fv(TH_TEXT_HI, color);
else
- UI_ThemeColor(TH_TEXT);
+ UI_GetThemeColor4fv(TH_TEXT, color);
float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
- glVertex2f(fx, fy);
+ immAttrib4fv(col, color);
+ immVertex2f(pos, fx, fy);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
/* restore scissortest */
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
/* outline */
- glColor3ubv((unsigned char *)wcol->outline);
- fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv((unsigned char *)wcol->outline);
+ imm_draw_line_box(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ immUnbindProgram();
}
void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
@@ -1540,7 +1624,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (scopes->track_disabled) {
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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
ok = true;
}
@@ -1567,54 +1651,66 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
}
if (!ok && scopes->track_preview) {
- glPushMatrix();
+ gpuMatrixBegin3D_legacy();
+ gpuPushMatrix();
/* draw content of pattern area */
glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]);
if (width > 0 && height > 0) {
ImBuf *drawibuf = scopes->track_preview;
+ float img_col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ float col_sel[4], col_outline[4];
if (scopes->use_track_mask) {
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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
- glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y,
- drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect);
+ immDrawPixelsTex(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, img_col);
/* draw cross for pixel position */
- glTranslatef(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.f);
+ gpuTranslate3f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.0f);
glScissor(ar->winrct.xmin + rect.xmin,
ar->winrct.ymin + rect.ymin,
BLI_rctf_size_x(&rect),
BLI_rctf_size_y(&rect));
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
-
- for (int a = 0; a < 2; a++) {
- if (a == 1) {
- GPU_basic_shader_bind_enable(GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
- UI_ThemeColor(TH_SEL_MARKER);
- }
- else {
- UI_ThemeColor(TH_MARKER_OUTLINE);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel);
+ UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline);
+
+ /* Do stipple cross with geometry */
+ immBegin(GL_LINES, 7*2*2);
+ float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f};
+ for (int axe = 0; axe < 2; ++axe) {
+ for (int i = 0; i < 7; ++i) {
+ float x1 = pos_sel[i] * (1 - axe);
+ float y1 = pos_sel[i] * axe;
+ float x2 = pos_sel[i+1] * (1 - axe);
+ float y2 = pos_sel[i+1] * axe;
+
+ if (i % 2 == 1)
+ immAttrib4fv(col, col_sel);
+ else
+ immAttrib4fv(col, col_outline);
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
}
-
- glBegin(GL_LINES);
- glVertex2f(-10.0f, 0.0f);
- glVertex2f(10.0f, 0.0f);
- glVertex2f(0.0f, -10.0f);
- glVertex2f(0.0f, 10.0f);
- glEnd();
}
+ immEnd();
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immUnbindProgram();
}
- glPopMatrix();
+ gpuPopMatrix();
+ gpuMatrixEnd();
ok = true;
}
@@ -1622,7 +1718,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (!ok) {
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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
/* outline */
@@ -1668,26 +1764,31 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
BLI_rcti_size_x(&scissor_new),
BLI_rcti_size_y(&scissor_new));
- glColor4ubv(but->col);
-
float x = 0.5f * (recti->xmin + recti->xmax);
float y = 0.5f * (recti->ymin + recti->ymax);
-
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(but->col);
+
glEnable(GL_BLEND);
- glBegin(GL_POLYGON);
+ immBegin(GL_TRIANGLE_FAN, 16);
for (int a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
+ immVertex2f(pos, x + size * si[a], y + size * co[a]);
+ immEnd();
- glColor4ub(0, 0, 0, 150);
+ immUniformColor4ub(0, 0, 0, 150);
glLineWidth(1);
glEnable(GL_LINE_SMOOTH);
- glBegin(GL_LINE_LOOP);
+ immBegin(GL_LINE_LOOP, 16);
for (int a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
+ immVertex2f(pos, x + size * si[a], y + size * co[a]);
+ immEnd();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
+
+ immUnbindProgram();
/* restore scissortest */
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
@@ -1752,8 +1853,8 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
{
float rad;
- if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f)
- rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f;
+ if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f)
+ rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f;
else
rad = radius;
@@ -1775,7 +1876,7 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
for (; i--; a -= aspect) {
/* alpha ranges from 2 to 20 or so */
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);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
calpha += dalpha;
}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 0a21c89e692..a50c0f5a4f4 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -597,7 +597,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
const int mval[2] = {
mx - ar->winrct.xmin,
my - ar->winrct.ymin};
- Base *base;
+ BaseLegacy *base;
CTX_wm_area_set(C, sa);
CTX_wm_region_set(C, ar);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 0573e8d9c94..a9cdb34f634 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -35,6 +35,7 @@
#include "GPU_extensions.h"
#include "GPU_basic_shader.h"
+#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "BLI_blenlib.h"
@@ -60,7 +61,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_thumbs.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "ED_datafiles.h"
@@ -225,13 +225,17 @@ static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float
viconutil_set_point(pts[1], cx - d2, cy - d);
viconutil_set_point(pts[2], cx + d2, cy);
- glColor4f(0.2f, 0.2f, 0.2f, alpha);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.2f, 0.2f, 0.2f, alpha);
- glBegin(GL_TRIANGLES);
- glVertex2iv(pts[0]);
- glVertex2iv(pts[1]);
- glVertex2iv(pts[2]);
- glEnd();
+ immBegin(PRIM_TRIANGLES, 3);
+ immVertex2iv(pos, pts[0]);
+ immVertex2iv(pos, pts[1]);
+ immVertex2iv(pos, pts[2]);
+ immEnd();
+
+ immUnbindProgram();
}
static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha, short key_type)
@@ -240,7 +244,6 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
* (since we're doing this offscreen, free from any particular space_id)
*/
struct bThemeState theme_state;
- int xco, yco;
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_ACTION, RGN_TYPE_WINDOW);
@@ -249,16 +252,30 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
* while the draw_keyframe_shape() function needs the midpoint for
* the keyframe
*/
- xco = x + w / 2;
- yco = y + h / 2;
+ int xco = x + w / 2;
+ int yco = y + h / 2;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT);
+ unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+ unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(PRIM_POINTS, 1);
/* draw keyframe
- * - xscale: 1.0 (since there's no timeline scaling to compensate for)
- * - yscale: 0.3 * h (found out experimentally... dunno why!)
+ * - size: 0.3 * h (found out experimentally... dunno why!)
* - sel: true (so that "keyframe" state shows the iconic yellow icon)
*/
- draw_keyframe_shape(xco, yco, 1.0f, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha);
-
+ draw_keyframe_shape(xco, yco, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha,
+ pos_id, size_id, color_id, outline_color_id);
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+
UI_Theme_Restore(&theme_state);
}
@@ -291,7 +308,7 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU
{
bTheme *btheme = UI_GetTheme();
ThemeWireColor *cs = &btheme->tarm[index];
-
+
/* Draw three bands of color: One per color
* x-----a-----b-----c
* | N | S | A |
@@ -300,19 +317,24 @@ static void vicon_colorset_draw(int index, int x, int y, int w, int h, float UNU
const int a = x + w / 3;
const int b = x + w / 3 * 2;
const int c = x + w;
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* XXX: Include alpha into this... */
/* normal */
- glColor3ubv((unsigned char *)cs->solid);
- glRecti(x, y, a, y + h);
-
+ immUniformColor3ubv((unsigned char *)cs->solid);
+ immRecti(pos, x, y, a, y + h);
+
/* selected */
- glColor3ubv((unsigned char *)cs->select);
- glRecti(a, y, b, y + h);
-
+ immUniformColor3ubv((unsigned char *)cs->select);
+ immRecti(pos, a, y, b, y + h);
+
/* active */
- glColor3ubv((unsigned char *)cs->active);
- glRecti(b, y, c, y + h);
+ immUniformColor3ubv((unsigned char *)cs->active);
+ immRecti(pos, b, y, c, y + h);
+
+ immUnbindProgram();
}
#define DEF_VICON_COLORSET_DRAW_NTH(prefix, index) \
@@ -1034,8 +1056,8 @@ static void icon_draw_texture(
unsigned texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
- if (rgb) immUniform4f("color", rgb[0], rgb[1], rgb[2], alpha);
- else immUniform4f("color", alpha, alpha, alpha, alpha);
+ if (rgb) immUniformColor3fvAlpha(rgb, alpha);
+ else immUniformColor4f(alpha, alpha, alpha, alpha);
immUniform1i("image", 0);
@@ -1385,6 +1407,14 @@ int UI_idcode_icon_get(const int idcode)
}
}
+/**
+ * \param set_idx: A value from #rna_enum_color_sets_items.
+ */
+int UI_colorset_icon_get(const int set_idx)
+{
+ return (set_idx < 1) ? ICON_NONE : VICO_COLORSET_01_VEC - 1 + set_idx;
+}
+
static void icon_draw_at_size(
float x, float y, int icon_id, float aspect, float alpha,
enum eIconSizes size, const bool nocreate)
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 7262b453e02..ca2538022b0 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2078,15 +2078,7 @@ static void ui_litem_estimate_row(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
- if (item->type == ITEM_BUTTON) {
- const uiBut *but = ((uiButtonItem *)item)->but;
- const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0');
-
- min_size_flag = min_size_flag && icon_only;
- }
- else {
- min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
- }
+ min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
litem->w += itemw;
litem->h = MAX2(itemh, litem->h);
@@ -2232,15 +2224,7 @@ static void ui_litem_estimate_column(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
- if (item->type == ITEM_BUTTON) {
- const uiBut *but = ((uiButtonItem *)item)->but;
- const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0');
-
- min_size_flag = min_size_flag && icon_only;
- }
- else {
- min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
- }
+ min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
litem->w = MAX2(litem->w, itemw);
litem->h += itemh;
@@ -3336,6 +3320,14 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
bitem->item.type = ITEM_BUTTON;
bitem->but = but;
+
+ int w, h;
+ ui_item_size((uiItem *)bitem, &w, &h);
+ /* XXX uiBut hasn't scaled yet
+ * we can flag the button as not expandable, depending on its size */
+ if (w <= 2 * UI_UNIT_X)
+ bitem->item.flag |= UI_ITEM_MIN;
+
BLI_addtail(&layout->items, bitem);
if (layout->context) {
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index dd06147f226..1bdc47e5037 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -536,29 +536,29 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
rcti hrect;
int pnl_icons;
const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname;
+ unsigned char col_title[4];
/* + 0.001f to avoid flirting with float inaccuracy */
if (panel->control & UI_PNL_CLOSE)
pnl_icons = (panel->labelofs + 2 * PNL_ICON + 5) / block->aspect + 0.001f;
else
pnl_icons = (panel->labelofs + PNL_ICON + 5) / block->aspect + 0.001f;
-
- /* active tab */
+
/* draw text label */
- UI_ThemeColor(TH_TITLE);
-
+ UI_GetThemeColor4ubv(TH_TITLE, col_title);
+
hrect = *rect;
if (dir == 'h') {
hrect.xmin = rect->xmin + pnl_icons;
hrect.ymin += 2.0f / block->aspect;
- UI_fontstyle_draw(&style->paneltitle, &hrect, activename);
+ UI_fontstyle_draw(&style->paneltitle, &hrect, activename, col_title);
}
else {
/* ignore 'pnl_icons', otherwise the text gets offset horizontally
* + 0.001f to avoid flirting with float inaccuracy
*/
hrect.xmin = rect->xmin + (PNL_ICON + 5) / block->aspect + 0.001f;
- UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename);
+ UI_fontstyle_draw_rotated(&style->paneltitle, &hrect, activename, col_title);
}
}
@@ -569,6 +569,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
rcti headrect;
rctf itemrect;
int ofsx;
+ float color[4];
const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false;
const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false;
@@ -659,8 +660,8 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
if (panel->control & UI_PNL_SOLID) UI_draw_roundbox_corner_set(UI_CNR_ALL);
else UI_draw_roundbox_corner_set(UI_CNR_NONE);
- UI_ThemeColorShade(TH_BACK, -120);
- UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8);
+ UI_GetThemeColorShade4fv(TH_BACK, -120, color);
+ UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color);
}
/* panel backdrop */
@@ -1805,7 +1806,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* tab titles */
/* draw white shadow to give text more depth */
- glColor3ubv(theme_col_text);
+ BLF_color3ubv(fontid, theme_col_text);
/* main tab title */
BLF_draw(fontid, category_id_draw, category_draw_len);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 62bab15dfb3..b78fa0706c0 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -194,6 +194,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
uiWidgetColors *theme = ui_tooltip_get_theme();
rcti bbox = data->bbox;
float tip_colors[UI_TIP_LC_MAX][3];
+ unsigned char drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */
float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */
float *value_color = tip_colors[UI_TIP_LC_VALUE];
@@ -260,9 +261,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
fstyle_header.shadowalpha = 1.0f;
fstyle_header.word_wrap = true;
+ rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]);
UI_fontstyle_set(&fstyle_header);
- glColor3fv(tip_colors[UI_TIP_LC_MAIN]);
- UI_fontstyle_draw(&fstyle_header, &bbox, data->header);
+ UI_fontstyle_draw(&fstyle_header, &bbox, data->header, drawcol);
/* offset to the end of the last line */
xofs = data->line_geom[i].x_pos;
@@ -270,9 +271,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
bbox.xmin += xofs;
bbox.ymax -= yofs;
- glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]);
+ rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]);
fstyle_header.shadow = 0;
- UI_fontstyle_draw(&fstyle_header, &bbox, data->active_info);
+ UI_fontstyle_draw(&fstyle_header, &bbox, data->active_info, drawcol);
/* undo offset */
bbox.xmin -= xofs;
@@ -280,14 +281,15 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
}
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
uiFontStyle fstyle_mono = data->fstyle;
+
fstyle_mono.uifont_id = blf_mono_font;
fstyle_mono.word_wrap = true;
UI_fontstyle_set(&fstyle_mono);
/* XXX, needed because we dont have mono in 'U.uifonts' */
BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi);
- glColor3fv(tip_colors[data->format[i].color_id]);
- UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i]);
+ rgb_float_to_uchar(drawcol, tip_colors[data->format[i].color_id]);
+ UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i], drawcol);
}
else {
uiFontStyle fstyle_normal = data->fstyle;
@@ -296,8 +298,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
/* draw remaining data */
UI_fontstyle_set(&fstyle_normal);
- glColor3fv(tip_colors[data->format[i].color_id]);
- UI_fontstyle_draw(&fstyle_normal, &bbox, data->lines[i]);
+ rgb_float_to_uchar(drawcol, tip_colors[data->format[i].color_id]);
+ UI_fontstyle_draw(&fstyle_normal, &bbox, data->lines[i], drawcol);
}
bbox.ymax -= data->lineh * data->line_geom[i].lines;
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 8bba8fc5534..01bce9d7bdc 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -149,7 +149,7 @@ static uiFont *uifont_to_blfont(int id)
void UI_fontstyle_draw_ex(
- const uiFontStyle *fs, const rcti *rect, const char *str,
+ const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4],
size_t len, float *r_xofs, float *r_yofs)
{
int xofs = 0, yofs;
@@ -196,6 +196,7 @@ void UI_fontstyle_draw_ex(
/* clip is very strict, so we give it some space */
BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4);
BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
+ BLF_color4ubv(fs->uifont_id, col);
BLF_draw(fs->uifont_id, str, len);
@@ -205,17 +206,17 @@ void UI_fontstyle_draw_ex(
*r_yofs = yofs;
}
-void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4])
{
float xofs, yofs;
UI_fontstyle_draw_ex(
- fs, rect, str,
+ fs, rect, str, col,
BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
}
/* drawn same as above, but at 90 degree angle */
-void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str, const unsigned char col[4])
{
float height;
int xofs, yofs;
@@ -249,6 +250,7 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch
BLF_enable(fs->uifont_id, BLF_ROTATION);
BLF_rotation(fs->uifont_id, angle);
+ BLF_color4ubv(fs->uifont_id, col);
if (fs->shadow) {
BLF_enable(fs->uifont_id, BLF_SHADOW);
@@ -275,13 +277,14 @@ void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const ch
*
* For drawing on-screen labels.
*/
-void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str)
+void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const unsigned char col[4])
{
if (fs->kerning == 1)
BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
UI_fontstyle_set(fs);
BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4ubv(fs->uifont_id, col);
BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
if (fs->kerning == 1)
@@ -315,12 +318,11 @@ void UI_fontstyle_draw_simple_backdrop(
x + width + margin,
(y + decent) + height + margin,
margin, col_bg);
-
- glColor4fv(col_fg);
}
BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_color4fv(fs->uifont_id, col_fg);
BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
if (fs->kerning == 1)
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index b75ecf68136..ff4762ccc6a 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1251,6 +1251,7 @@ static void widget_draw_text_ime_underline(
int ofs_x, width;
int rect_x = BLI_rcti_size_x(rect);
int sel_start = ime_data->sel_start, sel_end = ime_data->sel_end;
+ float fcol[4];
if (drawstr[0] != 0) {
if (but->pos >= but->ofs) {
@@ -1263,8 +1264,8 @@ static void widget_draw_text_ime_underline(
width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
ime_data->composite_len + but->pos - but->ofs);
- glColor4ubv((unsigned char *)wcol->text);
- UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1);
+ rgba_uchar_to_float(fcol, wcol->text);
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 1, fcol);
/* draw the thick line */
if (sel_start != -1 && sel_end != -1) {
@@ -1281,7 +1282,7 @@ static void widget_draw_text_ime_underline(
width = BLF_width(fstyle->uifont_id, drawstr + but->ofs,
sel_end + sel_start - but->ofs);
- UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2);
+ UI_draw_text_underline(rect->xmin + ofs_x, rect->ymin + 6 * U.pixelsize, min_ii(width, rect_x - 2) - ofs_x, 2, fcol);
}
}
}
@@ -1457,8 +1458,6 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
#endif
- glColor4ubv((unsigned char *)wcol->text);
-
if (!use_right_only) {
/* for underline drawing */
float font_xofs, font_yofs;
@@ -1466,7 +1465,8 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs);
if (drawlen > 0) {
- UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, drawlen, &font_xofs, &font_yofs);
+ UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, (unsigned char *)wcol->text,
+ drawlen, &font_xofs, &font_yofs);
if (but->menu_key != '\0') {
char fixedbuf[128];
@@ -1492,6 +1492,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
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_color4ubv(fstyle->uifont_id, (unsigned char *)wcol->text);
BLF_draw(fstyle->uifont_id, "_", 2);
if (fstyle->kerning == 1) {
@@ -1506,7 +1507,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
if (drawstr_right) {
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax -= UI_TEXT_CLIP_MARGIN;
- UI_fontstyle_draw(fstyle, rect, drawstr_right);
+ UI_fontstyle_draw(fstyle, rect, drawstr_right, (unsigned char *)wcol->text);
}
}
@@ -1575,7 +1576,10 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
}
}
- if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
+ if (but->drawflag & UI_BUT_TEXT_NO_MARGIN) {
+ /* skip */
+ }
+ else if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) {
@@ -4125,8 +4129,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
}
- glColor4ubv((unsigned char *)wt->wcol.text);
- UI_fontstyle_draw(fstyle, rect, drawstr);
+ UI_fontstyle_draw(fstyle, rect, drawstr, (unsigned char *)wt->wcol.text);
}
/* part text right aligned */
@@ -4134,7 +4137,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
if (cpoin) {
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax = _rect.xmax - 5;
- UI_fontstyle_draw(fstyle, rect, cpoin + 1);
+ UI_fontstyle_draw(fstyle, rect, cpoin + 1, (unsigned char *)wt->wcol.text);
*cpoin = UI_SEP_CHAR;
}
}
@@ -4192,7 +4195,6 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
BLI_strncpy(drawstr, name, sizeof(drawstr));
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
- glColor4ubv((unsigned char *)wt->wcol.text);
- UI_fontstyle_draw(fstyle, &trect, drawstr);
+ UI_fontstyle_draw(fstyle, &trect, drawstr, (unsigned char *)wt->wcol.text);
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 8b8c842b2c7..bf7fc0b8bd5 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -54,6 +54,8 @@
#include "BIF_gl.h"
+#include "BLF_api.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -166,6 +168,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case SPACE_CLIP:
ts = &btheme->tclip;
break;
+ case SPACE_COLLECTIONS:
+ ts = &btheme->tcollections;
+ break;
default:
ts = &btheme->tv3d;
break;
@@ -1207,6 +1212,11 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
btheme->tclip.handle_vertex_size = 5;
ui_theme_space_init_handles_color(&btheme->tclip);
+
+ /* space collection manager */
+ btheme->tcollections = btheme->tv3d;
+ rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0);
+ rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */
}
void ui_style_init_default(void)
@@ -1278,18 +1288,11 @@ void UI_ThemeColor4(int colorid)
/* set the color with offset for shades */
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);
- g = offset + (int) cp[1];
- CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
- CLAMP(b, 0, 255);
- glColor4ub(r, g, b, cp[3]);
+ unsigned char col[4];
+ UI_GetThemeColorShade4ubv(colorid, offset, col);
+ glColor4ubv(col);
}
+
void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
{
int r, g, b, a;
@@ -1394,6 +1397,12 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off
glColor4ub(r, g, b, a);
}
+void UI_FontThemeColor(int fontid, int colorid)
+{
+ unsigned char color[4];
+ UI_GetThemeColor4ubv(colorid, color);
+ BLF_color4ubv(fontid, color);
+}
/* get individual values, not scaled */
float UI_GetThemeValuef(int colorid)
@@ -1492,6 +1501,42 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3])
col[2] = b;
}
+void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int offset, unsigned char col[3])
+{
+ 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);
+ col[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ col[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ col[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+
+ CLAMP(col[0], 0, 255);
+ CLAMP(col[1], 0, 255);
+ CLAMP(col[2], 0, 255);
+}
+
+void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4])
+{
+ 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);
+ g = offset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b = offset + (int) cp[2];
+ CLAMP(b, 0, 255);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = cp[3];
+}
+
void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
{
int r, g, b, a;
@@ -2818,6 +2863,12 @@ void init_userdef_do_versions(void)
*/
{
for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
+ btheme->tcollections = btheme->tv3d;
+ rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0);
+ rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */
+ }
+
+ for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set_fl(btheme->tui.xaxis, 1.0f, 0.27f, 0.27f, 1.0f); /* red */
rgba_char_args_set_fl(btheme->tui.yaxis, 0.27f, 1.0f, 0.27f, 1.0f); /* green */
rgba_char_args_set_fl(btheme->tui.zaxis, 0.27f, 0.27f, 1.0f, 1.0f); /* blue */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index a358118aed1..bcac8d0b825 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1855,6 +1855,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* scale indicators */
if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
+ const int font_id = BLF_default();
View2DGrid *grid = vs->grid;
float fac, dfac, fac2, val;
@@ -1869,7 +1870,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
dfac = dfac * BLI_rcti_size_x(&hor);
/* set starting value, and text color */
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(font_id, TH_TEXT);
val = grid->startx;
/* if we're clamping to whole numbers only, make sure entries won't be repeated */
@@ -1881,7 +1882,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
}
if (vs->xunits == V2D_UNIT_FRAMES)
grid->powerx = 1;
-
+
/* draw numbers in the appropriate range */
if (dfac > 0.0f) {
float h = 0.1f * UI_UNIT_Y + (float)(hor.ymin);
@@ -1978,7 +1979,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
dfac = dfac * BLI_rcti_size_y(&vert);
/* set starting value, and text color */
- UI_ThemeColor(TH_TEXT);
+ const int font_id = BLF_default();
+ UI_FontThemeColor(font_id, TH_TEXT);
val = grid->starty;
/* if vertical clamping (to whole numbers) is used (i.e. in Sequencer), apply correction */
@@ -1987,9 +1989,8 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* draw vertical steps */
if (dfac > 0.0f) {
-
- BLF_rotation_default(M_PI_2);
- BLF_enable_default(BLF_ROTATION);
+ BLF_rotation(font_id, M_PI_2);
+ BLF_enable(font_id, BLF_ROTATION);
for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) {
@@ -2000,7 +2001,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
scroll_printstr(scene, (float)(vert.xmax) - 2.0f, fac, val, grid->powery, vs->yunits, 'v');
}
- BLF_disable_default(BLF_ROTATION);
+ BLF_disable(font_id, BLF_ROTATION);
}
}
}
@@ -2514,7 +2515,8 @@ void UI_view2d_text_cache_draw(ARegion *ar)
int col_pack_prev = 0;
/* investigate using BLF_ascender() */
- const float default_height = g_v2d_strings ? BLF_height_default("28", 3) : 0.0f;
+ const int font_id = BLF_default();
+ const float default_height = g_v2d_strings ? BLF_height(font_id, "28", 3) : 0.0f;
wmOrtho2_region_pixelspace(ar);
@@ -2525,7 +2527,7 @@ void UI_view2d_text_cache_draw(ARegion *ar)
if (yofs < 1) yofs = 1;
if (col_pack_prev != v2s->col.pack) {
- glColor3ubv(v2s->col.ub);
+ BLF_color3ubv(font_id, v2s->col.ub);
col_pack_prev = v2s->col.pack;
}
@@ -2533,11 +2535,11 @@ void UI_view2d_text_cache_draw(ARegion *ar)
BLF_draw_default((float)(v2s->mval[0] + xofs), (float)(v2s->mval[1] + yofs), 0.0,
v2s->str, BLF_DRAW_STR_DUMMY_MAX);
else {
- BLF_clipping_default(v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
- BLF_enable_default(BLF_CLIPPING);
+ BLF_enable(font_id, BLF_CLIPPING);
+ BLF_clipping(font_id, v2s->rect.xmin - 4, v2s->rect.ymin - 4, v2s->rect.xmax + 4, v2s->rect.ymax + 4);
BLF_draw_default(v2s->rect.xmin + xofs, v2s->rect.ymin + yofs, 0.0f,
v2s->str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_disable_default(BLF_CLIPPING);
+ BLF_disable(font_id, BLF_CLIPPING);
}
}
g_v2d_strings = NULL;
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index d2b2f12c1a5..fa2c1f25cfc 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -447,7 +447,8 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltax", 0);
RNA_int_set(op->ptr, "deltay", -40);
- if (RNA_boolean_get(op->ptr, "page")) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page");
+ if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) {
ARegion *ar = CTX_wm_region(C);
RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax);
}
@@ -497,7 +498,8 @@ static int view_scrollup_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltax", 0);
RNA_int_set(op->ptr, "deltay", 40);
- if (RNA_boolean_get(op->ptr, "page")) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page");
+ if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) {
ARegion *ar = CTX_wm_region(C);
RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask));
}
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index bf59693b856..2250aaab310 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -57,6 +57,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
+#include "GPU_immediate.h"
+
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_view3d.h"
@@ -1002,12 +1004,18 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
copy_v3_v3(v2, ray_hit_best[1]);
}
- UI_ThemeColor(TH_TRANSFORM);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_TRANSFORM);
glLineWidth(2.0);
- glBegin(GL_LINES);
- glVertex3fv(v1);
- glVertex3fv(v2);
- glEnd();
+
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ immUnbindProgram();
}
static void knife_init_colors(KnifeColors *colors)
@@ -1038,63 +1046,66 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glPushMatrix();
glMultMatrixf(kcd->ob->obmat);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
if (kcd->mode == MODE_DRAGGING) {
if (kcd->is_angle_snapping)
knifetool_draw_angle_snapping(kcd);
- glColor3ubv(kcd->colors.line);
-
+ immUniformColor3ubv(kcd->colors.line);
glLineWidth(2.0);
- glBegin(GL_LINES);
- glVertex3fv(kcd->prev.cage);
- glVertex3fv(kcd->curr.cage);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, kcd->prev.cage);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
}
if (kcd->prev.vert) {
- glColor3ubv(kcd->colors.point);
+ immUniformColor3ubv(kcd->colors.point);
glPointSize(11);
- glBegin(GL_POINTS);
- glVertex3fv(kcd->prev.cage);
- glEnd();
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, kcd->prev.cage);
+ immEnd();
}
if (kcd->prev.bmface) {
- glColor3ubv(kcd->colors.curpoint);
+ immUniformColor3ubv(kcd->colors.curpoint);
glPointSize(9);
- glBegin(GL_POINTS);
- glVertex3fv(kcd->prev.cage);
- glEnd();
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, kcd->prev.cage);
+ immEnd();
}
if (kcd->curr.edge) {
- glColor3ubv(kcd->colors.edge);
+ immUniformColor3ubv(kcd->colors.edge);
glLineWidth(2.0);
- glBegin(GL_LINES);
- glVertex3fv(kcd->curr.edge->v1->cageco);
- glVertex3fv(kcd->curr.edge->v2->cageco);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, kcd->curr.edge->v1->cageco);
+ immVertex3fv(pos, kcd->curr.edge->v2->cageco);
+ immEnd();
}
else if (kcd->curr.vert) {
- glColor3ubv(kcd->colors.point);
+ immUniformColor3ubv(kcd->colors.point);
glPointSize(11);
- glBegin(GL_POINTS);
- glVertex3fv(kcd->curr.cage);
- glEnd();
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
}
if (kcd->curr.bmface) {
- glColor3ubv(kcd->colors.curpoint);
+ immUniformColor3ubv(kcd->colors.curpoint);
glPointSize(9);
- glBegin(GL_POINTS);
- glVertex3fv(kcd->curr.cage);
- glEnd();
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
}
if (kcd->totlinehit > 0) {
@@ -1105,26 +1116,35 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* draw any snapped verts first */
- glColor4ubv(kcd->colors.point_a);
+ immUniformColor4ubv(kcd->colors.point_a);
glPointSize(11);
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GL_POINTS, kcd->totlinehit);
+
lh = kcd->linehits;
for (i = 0; i < kcd->totlinehit; i++, lh++) {
- if (lh->v)
- glVertex3fv(lh->cagehit);
+ if (lh->v) {
+ immVertex3fv(pos, lh->cagehit);
+ }
}
- glEnd();
+
+ immEnd();
/* now draw the rest */
- glColor4ubv(kcd->colors.curpoint_a);
+ immUniformColor4ubv(kcd->colors.curpoint_a);
glPointSize(7);
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GL_POINTS, kcd->totlinehit);
+
lh = kcd->linehits;
for (i = 0; i < kcd->totlinehit; i++, lh++) {
- if (!lh->v)
- glVertex3fv(lh->cagehit);
+ if (!lh->v) {
+ immVertex3fv(pos, lh->cagehit);
+ }
}
- glEnd();
+
+ immEnd();
+
glDisable(GL_BLEND);
}
@@ -1132,43 +1152,45 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
BLI_mempool_iter iter;
KnifeEdge *kfe;
+ immUniformColor3ubv(kcd->colors.line);
glLineWidth(1.0);
- glBegin(GL_LINES);
+
+ immBeginAtMost(GL_LINES, BLI_mempool_count(kcd->kedges) * 2);
BLI_mempool_iternew(kcd->kedges, &iter);
for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) {
if (!kfe->is_cut)
continue;
- glColor3ubv(kcd->colors.line);
-
- glVertex3fv(kfe->v1->cageco);
- glVertex3fv(kfe->v2->cageco);
+ immVertex3fv(pos, kfe->v1->cageco);
+ immVertex3fv(pos, kfe->v2->cageco);
}
- glEnd();
+ immEnd();
}
if (kcd->totkvert > 0) {
BLI_mempool_iter iter;
KnifeVert *kfv;
+ immUniformColor3ubv(kcd->colors.point);
glPointSize(5.0);
- glBegin(GL_POINTS);
+ immBeginAtMost(GL_POINTS, BLI_mempool_count(kcd->kverts));
+
BLI_mempool_iternew(kcd->kverts, &iter);
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
if (!kfv->is_cut)
continue;
- glColor3ubv(kcd->colors.point);
-
- glVertex3fv(kfv->cageco);
+ immVertex3fv(pos, kfv->cageco);
}
- glEnd();
+ immEnd();
}
+ immUnbindProgram();
+
glPopMatrix();
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index f1c1e4105d0..6d8a220dd86 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -45,7 +45,8 @@
#include "BKE_DerivedMesh.h"
#include "BKE_unit.h"
-#include "BIF_gl.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "UI_interface.h"
@@ -104,27 +105,41 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (v3d && v3d->zbuf)
glDisable(GL_DEPTH_TEST);
- glPushMatrix();
- glMultMatrixf(lcd->ob->obmat);
+ gpuMatrixBegin3D_legacy();
+ gpuMultMatrix3D(lcd->ob->obmat);
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ub(255, 0, 255);
- glColor3ub(255, 0, 255);
if (lcd->totedge > 0) {
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, lcd->edges);
- glDrawArrays(GL_LINES, 0, lcd->totedge * 2);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immBegin(GL_LINES, lcd->totedge * 2);
+
+ for (int i = 0; i < lcd->totedge; i++) {
+ immVertex3fv(pos, lcd->edges[i][0]);
+ immVertex3fv(pos, lcd->edges[i][1]);
+ }
+
+ immEnd();
}
if (lcd->totpoint > 0) {
glPointSize(3.0f);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, lcd->points);
- glDrawArrays(GL_POINTS, 0, lcd->totpoint);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immBegin(GL_POINTS, lcd->totpoint);
+
+ for (int i = 0; i < lcd->totpoint; i++) {
+ immVertex3fv(pos, lcd->points[i]);
+ }
+
+ immEnd();
}
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuMatrixEnd();
+
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 8f004bcf72b..d76dba4088a 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -47,6 +47,7 @@
#include "BLI_rand.h"
#include "BLI_sort_utils.h"
+#include "BKE_layer.h"
#include "BKE_material.h"
#include "BKE_context.h"
#include "BKE_deform.h"
@@ -306,7 +307,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE,
+ CTX_data_main(C), CTX_data_scene(C), 0,
ar, CTX_wm_view3d(C));
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
@@ -3010,7 +3011,7 @@ enum {
MESH_SEPARATE_LOOSE = 2,
};
-static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static Base *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
{
Base *base_new;
Object *obedit = base_old->object;
@@ -3031,11 +3032,11 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
- base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH);
+ base_new = ED_object_add_duplicate(bmain, scene, sl, base_old, USER_DUP_MESH);
/* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */
assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
- ED_base_object_select(base_new, BA_SELECT);
+ ED_object_base_select(base_new, BA_SELECT);
BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
"duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new);
@@ -3057,7 +3058,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
return base_new;
}
-static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_selected(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
{
/* we may have tags from previous operators */
BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
@@ -3065,7 +3066,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM
/* sel -> tag */
BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT);
- return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
+ return (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
}
/* flush a hflag to from verts to edges/faces */
@@ -3164,7 +3165,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
}
}
-static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_material(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
{
BMFace *f_cmp, *f;
BMIter iter;
@@ -3205,7 +3206,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
}
/* Move selection into a separate object */
- base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old);
+ base_new = mesh_separate_tagged(bmain, scene, sl, base_old, bm_old);
if (base_new) {
mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr);
}
@@ -3216,7 +3217,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
return result;
}
-static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_loose(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
{
int i;
BMEdge *e;
@@ -3269,7 +3270,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
/* Move selection into a separate object */
- result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
+ result |= (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
}
return result;
@@ -3279,6 +3280,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
const int type = RNA_enum_get(op->ptr, "type");
int retval = 0;
@@ -3299,13 +3301,13 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
/* editmode separate */
switch (type) {
case MESH_SEPARATE_SELECTED:
- retval = mesh_separate_selected(bmain, scene, base, em->bm);
+ retval = mesh_separate_selected(bmain, scene, sl, base, em->bm);
break;
case MESH_SEPARATE_MATERIAL:
- retval = mesh_separate_material(bmain, scene, base, em->bm);
+ retval = mesh_separate_material(bmain, scene, sl, base, em->bm);
break;
case MESH_SEPARATE_LOOSE:
- retval = mesh_separate_loose(bmain, scene, base, em->bm);
+ retval = mesh_separate_loose(bmain, scene, sl, base, em->bm);
break;
default:
BLI_assert(0);
@@ -3340,10 +3342,10 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
switch (type) {
case MESH_SEPARATE_MATERIAL:
- retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old);
+ retval_iter = mesh_separate_material(bmain, scene, sl, base_iter, bm_old);
break;
case MESH_SEPARATE_LOOSE:
- retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old);
+ retval_iter = mesh_separate_loose(bmain, scene, sl, base_iter, bm_old);
break;
default:
BLI_assert(0);
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 772bb1bd308..036d084a91c 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -551,7 +551,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- Base *base;
+ BaseLegacy *base;
Image *ima = NULL;
Mesh *me;
Object *obedit;
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index b95921964eb..443f2f0baa8 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -326,7 +326,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
}
static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh,
- Base *base, unsigned int lay)
+ BaseLegacy *base, unsigned int lay)
{
float co[3], rot[3];
BMEditMesh *em;
@@ -461,14 +461,15 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
static int navmesh_create_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
LinkNode *obs = NULL;
- Base *navmeshBase = NULL;
+ BaseLegacy *navmeshBase = NULL;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
if (base->object->type == OB_MESH) {
if (base->object->body_type == OB_BODY_TYPE_NAVMESH) {
- if (!navmeshBase || base == scene->basact) {
+ if (!navmeshBase || base == sl->basact) {
navmeshBase = base;
}
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index b26989113d4..c8b0955c70f 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -75,26 +75,213 @@
/* join selected meshes into the active mesh, context sensitive
* return 0 if no join is made (error) and 1 if the join is done */
+static void join_mesh_single(
+ Main *bmain, Scene *scene,
+ Object *ob_dst, Base *base_src, float imat[4][4],
+ MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp,
+ CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata,
+ int totvert, int totedge, int totloop, int totpoly,
+ Key *key, Key *nkey,
+ Material **matar, int *matmap, int totcol,
+ int *vertofs, int *edgeofs, int *loopofs, int *polyofs)
+{
+ int a, b;
+
+ Mesh *me = base_src->object->data;
+ MVert *mvert = *mvert_pp;
+ MEdge *medge = *medge_pp;
+ MLoop *mloop = *mloop_pp;
+ MPoly *mpoly = *mpoly_pp;
+
+ if (me->totvert) {
+ /* merge customdata flag */
+ ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag;
+
+ /* standard data */
+ CustomData_merge(&me->vdata, vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
+ CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
+
+ /* vertex groups */
+ MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
+
+ /* NB: vertex groups here are new version */
+ if (dvert) {
+ for (a = 0; a < me->totvert; a++) {
+ for (b = 0; b < dvert[a].totweight; b++) {
+ /* Find the old vertex group */
+ bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr);
+ int index;
+ if (odg) {
+ /* Search for a match in the new object, and set new index */
+ for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) {
+ if (STREQ(dg->name, odg->name)) {
+ dvert[a].dw[b].def_nr = index;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* if this is the object we're merging into, no need to do anything */
+ if (base_src->object != ob_dst) {
+ float cmat[4][4];
+
+ /* watch this: switch matmul order really goes wrong */
+ mul_m4_m4m4(cmat, imat, base_src->object->obmat);
+
+ /* transform vertex coordinates into new space */
+ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) {
+ mul_m4_v3(cmat, mvert->co);
+ }
+
+ /* for each shapekey in destination mesh:
+ * - if there's a matching one, copy it across (will need to transform vertices into new space...)
+ * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
+ */
+ if (key) {
+ /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ /* get pointer to where to write data for this mesh in shapekey's data array */
+ float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs;
+
+ /* check if this mesh has such a shapekey */
+ KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
+ if (okb) {
+ /* copy this mesh's shapekey to the destination shapekey (need to transform first) */
+ float (*ocos)[3] = okb->data;
+ for (a = 0; a < me->totvert; a++, cos++, ocos++) {
+ copy_v3_v3(*cos, *ocos);
+ mul_m4_v3(cmat, *cos);
+ }
+ }
+ else {
+ /* copy this mesh's vertex coordinates to the destination shapekey */
+ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
+ copy_v3_v3(*cos, mvert->co);
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* for each shapekey in destination mesh:
+ * - if it was an 'original', copy the appropriate data from nkey
+ * - otherwise, copy across plain coordinates (no need to transform coordinates)
+ */
+ if (key) {
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ /* get pointer to where to write data for this mesh in shapekey's data array */
+ float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs;
+
+ /* check if this was one of the original shapekeys */
+ KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
+ if (okb) {
+ /* copy this mesh's shapekey to the destination shapekey */
+ float (*ocos)[3] = okb->data;
+ for (a = 0; a < me->totvert; a++, cos++, ocos++) {
+ copy_v3_v3(*cos, *ocos);
+ }
+ }
+ else {
+ /* copy base-coordinates to the destination shapekey */
+ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
+ copy_v3_v3(*cos, mvert->co);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (me->totedge) {
+ CustomData_merge(&me->edata, edata, CD_MASK_MESH, CD_DEFAULT, totedge);
+ CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
+
+ for (a = 0; a < me->totedge; a++, medge++) {
+ medge->v1 += *vertofs;
+ medge->v2 += *vertofs;
+ }
+ }
+
+ if (me->totloop) {
+ if (base_src->object != ob_dst) {
+ MultiresModifierData *mmd;
+
+ multiresModifier_prepare_join(scene, base_src->object, ob_dst);
+
+ if ((mmd = get_multires_modifier(scene, base_src->object, true))) {
+ ED_object_iter_other(bmain, base_src->object, true,
+ ED_object_multires_update_totlevels_cb,
+ &mmd->totlvl);
+ }
+ }
+
+ CustomData_merge(&me->ldata, ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
+ CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
+
+ for (a = 0; a < me->totloop; a++, mloop++) {
+ mloop->v += *vertofs;
+ mloop->e += *edgeofs;
+ }
+ }
+
+ if (me->totpoly) {
+ if (matmap) {
+ /* make mapping for materials */
+ for (a = 1; a <= base_src->object->totcol; a++) {
+ Material *ma = give_current_material(base_src->object, a);
+
+ for (b = 0; b < totcol; b++) {
+ if (ma == matar[b]) {
+ matmap[a - 1] = b;
+ break;
+ }
+ }
+ }
+ }
+
+ CustomData_merge(&me->pdata, pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
+ CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
+
+ for (a = 0; a < me->totpoly; a++, mpoly++) {
+ mpoly->loopstart += *loopofs;
+ mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0;
+ }
+ }
+
+ /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
+ *vertofs += me->totvert;
+ *mvert_pp += me->totvert;
+ *edgeofs += me->totedge;
+ *medge_pp += me->totedge;
+ *loopofs += me->totloop;
+ *mloop_pp += me->totloop;
+ *polyofs += me->totpoly;
+ *mpoly_pp += me->totpoly;
+}
+
int join_mesh_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- Material **matar, *ma;
+ Base *ob_base = CTX_data_active_base(C);
+ Object *ob = ob_base->object;
+ Material **matar = NULL, *ma;
Mesh *me;
- MVert *mvert, *mv;
+ MVert *mvert = NULL;
MEdge *medge = NULL;
MPoly *mpoly = NULL;
MLoop *mloop = NULL;
Key *key, *nkey = NULL;
- KeyBlock *kb, *okb, *kbn;
- float imat[4][4], cmat[4][4], *fp1, *fp2;
+ KeyBlock *kb, *kbn;
+ float imat[4][4];
int a, b, totcol, totmat = 0, totedge = 0, totvert = 0;
int totloop = 0, totpoly = 0, vertofs, *matmap = NULL;
- int i, j, index, haskey = 0, edgeofs, loopofs, polyofs;
+ int i, haskey = 0, edgeofs, loopofs, polyofs;
bool ok = false;
bDeformGroup *dg, *odg;
- MDeformVert *dvert;
CustomData vdata, edata, fdata, ldata, pdata;
if (scene->obedit) {
@@ -154,8 +341,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
BKE_mesh_tessface_clear(me);
/* new material indices and material array */
- matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar");
- if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap");
+ if (totmat) {
+ matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar");
+ matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap");
+ }
totcol = ob->totcol;
/* obact materials in new main array, is nicer start! */
@@ -214,7 +403,9 @@ int join_mesh_exec(bContext *C, wmOperator *op)
ma = give_current_material(base->object, a);
for (b = 0; b < totcol; b++) {
- if (ma == matar[b]) break;
+ if (ma == matar[b]) {
+ break;
+ }
}
if (b == totcol) {
matar[b] = ma;
@@ -223,8 +414,9 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
totcol++;
}
- if (totcol >= MAXMAT)
+ if (totcol >= MAXMAT) {
break;
+ }
}
}
@@ -301,187 +493,41 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* inverse transform for all selected meshes in this object */
invert_m4_m4(imat, ob->obmat);
-
+
+ /* Add back active mesh first. This allows to keep things similar as they were, as much as possible (i.e. data from
+ * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084.
+ */
+ join_mesh_single(
+ bmain, scene,
+ ob, ob_base, imat,
+ &mvert, &medge, &mloop, &mpoly,
+ &vdata, &edata, &ldata, &pdata,
+ totvert, totedge, totloop, totpoly,
+ key, nkey,
+ matar, matmap, totcol,
+ &vertofs, &edgeofs, &loopofs, &polyofs);
+
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
+ if (base->object == ob) {
+ continue;
+ }
/* only join if this is a mesh */
if (base->object->type == OB_MESH) {
- me = base->object->data;
-
- if (me->totvert) {
-
- /* merge customdata flag */
- ((Mesh *)ob->data)->cd_flag |= me->cd_flag;
-
- /* standard data */
- CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
- CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert);
-
- /* vertex groups */
- dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT);
-
- /* NB: vertex groups here are new version */
- if (dvert) {
- for (i = 0; i < me->totvert; i++) {
- for (j = 0; j < dvert[i].totweight; j++) {
- /* Find the old vertex group */
- odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr);
- if (odg) {
- /* Search for a match in the new object, and set new index */
- for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) {
- if (STREQ(dg->name, odg->name)) {
- dvert[i].dw[j].def_nr = index;
- break;
- }
- }
- }
- }
- }
- }
-
- /* if this is the object we're merging into, no need to do anything */
- if (base->object != ob) {
- /* watch this: switch matmul order really goes wrong */
- mul_m4_m4m4(cmat, imat, base->object->obmat);
-
- /* transform vertex coordinates into new space */
- for (a = 0, mv = mvert; a < me->totvert; a++, mv++) {
- mul_m4_v3(cmat, mv->co);
- }
-
- /* for each shapekey in destination mesh:
- * - if there's a matching one, copy it across (will need to transform vertices into new space...)
- * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
- */
- if (key) {
- /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
- for (kb = key->block.first; kb; kb = kb->next) {
- /* get pointer to where to write data for this mesh in shapekey's data array */
- fp1 = ((float *)kb->data) + (vertofs * 3);
-
- /* check if this mesh has such a shapekey */
- okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
-
- if (okb) {
- /* copy this mesh's shapekey to the destination shapekey (need to transform first) */
- fp2 = ((float *)(okb->data));
- for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) {
- copy_v3_v3(fp1, fp2);
- mul_m4_v3(cmat, fp1);
- }
- }
- else {
- /* copy this mesh's vertex coordinates to the destination shapekey */
- mv = mvert;
- for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) {
- copy_v3_v3(fp1, mv->co);
- }
- }
- }
- }
- }
- else {
- /* for each shapekey in destination mesh:
- * - if it was an 'original', copy the appropriate data from nkey
- * - otherwise, copy across plain coordinates (no need to transform coordinates)
- */
- if (key) {
- for (kb = key->block.first; kb; kb = kb->next) {
- /* get pointer to where to write data for this mesh in shapekey's data array */
- fp1 = ((float *)kb->data) + (vertofs * 3);
-
- /* check if this was one of the original shapekeys */
- okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
- if (okb) {
- /* copy this mesh's shapekey to the destination shapekey */
- fp2 = ((float *)(okb->data));
- for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) {
- copy_v3_v3(fp1, fp2);
- }
- }
- else {
- /* copy base-coordinates to the destination shapekey */
- mv = mvert;
- for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) {
- copy_v3_v3(fp1, mv->co);
- }
- }
- }
- }
- }
-
- /* advance mvert pointer to end of base mesh's data */
- mvert += me->totvert;
- }
-
- if (me->totedge) {
- CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
- CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge);
-
- for (a = 0; a < me->totedge; a++, medge++) {
- medge->v1 += vertofs;
- medge->v2 += vertofs;
- }
- }
-
- if (me->totloop) {
- if (base->object != ob) {
- MultiresModifierData *mmd;
-
- multiresModifier_prepare_join(scene, base->object, ob);
+ join_mesh_single(
+ bmain, scene,
+ ob, base, imat,
+ &mvert, &medge, &mloop, &mpoly,
+ &vdata, &edata, &ldata, &pdata,
+ totvert, totedge, totloop, totpoly,
+ key, nkey,
+ matar, matmap, totcol,
+ &vertofs, &edgeofs, &loopofs, &polyofs);
- if ((mmd = get_multires_modifier(scene, base->object, true))) {
- ED_object_iter_other(bmain, base->object, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
- }
- }
-
- CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
- CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop);
-
- for (a = 0; a < me->totloop; a++, mloop++) {
- mloop->v += vertofs;
- mloop->e += edgeofs;
- }
- }
-
- if (me->totpoly) {
- if (totmat) {
- /* make mapping for materials */
- for (a = 1; a <= base->object->totcol; a++) {
- ma = give_current_material(base->object, a);
-
- for (b = 0; b < totcol; b++) {
- if (ma == matar[b]) {
- matmap[a - 1] = b;
- break;
- }
- }
- }
- }
-
- CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
- CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly);
-
- for (a = 0; a < me->totpoly; a++, mpoly++) {
- mpoly->loopstart += loopofs;
- mpoly->mat_nr = matmap ? matmap[(int)mpoly->mat_nr] : 0;
- }
-
- polyofs += me->totpoly;
- }
-
- /* these are used for relinking (cannot be set earlier,
- * or else reattaching goes wrong)
- */
- vertofs += me->totvert;
- edgeofs += me->totedge;
- loopofs += me->totloop;
-
/* free base, now that data is merged */
- if (base->object != ob)
- ED_base_object_free_and_unlink(bmain, scene, base);
+ if (base->object != ob) {
+ ED_base_object_free_and_unlink(bmain, scene, base->object);
+ }
}
}
CTX_DATA_END;
@@ -529,34 +575,20 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (totcol) {
me->mat = matar;
- ob->mat = MEM_callocN(sizeof(void *) * totcol, "join obmatar");
- ob->matbits = MEM_callocN(sizeof(char) * totcol, "join obmatbits");
+ ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar");
+ ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits");
+ MEM_freeN(matmap);
}
- else
- MEM_freeN(matar);
-
+
ob->totcol = me->totcol = totcol;
- if (matmap) MEM_freeN(matmap);
-
/* other mesh users */
test_all_objects_materials(bmain, (ID *)me);
/* free temp copy of destination shapekeys (if applicable) */
if (nkey) {
- /* XXX 2.5 Animato */
-#if 0
- /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */
- if (nkey->ipo) {
- BKE_ipo_free(nkey->ipo);
- BLI_remlink(&bmain->ipo, nkey->ipo);
- MEM_freeN(nkey->ipo);
- }
-#endif
-
- BKE_key_free(nkey);
- BLI_remlink(&bmain->key, nkey);
- MEM_freeN(nkey);
+ /* We can assume nobody is using that ID currently. */
+ BKE_libblock_free_ex(bmain, nkey, false, false);
}
/* ensure newly inserted keys are time sorted */
@@ -564,7 +596,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
BKE_key_sort(key);
}
- DAG_relations_tag_update(bmain); // removed objects, need to rebuild dag
+ DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 02b2d8492b4..e7223f6f1ee 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -63,6 +63,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
@@ -73,6 +74,7 @@
#include "BKE_group.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -405,10 +407,11 @@ Object *ED_object_add_type(
bContext *C,
int type, const char *name,
const float loc[3], const float rot[3],
- bool enter_editmode, unsigned int layer)
+ bool enter_editmode, unsigned int UNUSED(layer))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob;
/* for as long scene has editmode... */
@@ -416,13 +419,12 @@ Object *ED_object_add_type(
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
/* deselects all, sets scene->basact */
- ob = BKE_object_add(bmain, scene, type, name);
- BASACT->lay = ob->lay = layer;
+ ob = BKE_object_add(bmain, scene, sl, type, name);
/* editor level activate, notifiers */
- ED_base_object_activate(C, BASACT);
+ ED_object_base_activate(C, sl->basact);
/* more editor stuff */
- ED_object_base_init_transform(C, BASACT, loc, rot);
+ ED_object_base_init_transform(C, sl->basact, loc, rot);
/* Ignore collisions by default for non-mesh objects */
if (type != OB_MESH) {
@@ -830,7 +832,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
{
Scene *scene = CTX_data_scene(C);
- Base *base = NULL;
+ BaseLegacy *base = NULL;
Image *ima = NULL;
Object *ob = NULL;
@@ -1109,21 +1111,19 @@ static void object_delete_check_glsl_update(Object *ob)
/* remove base from a specific scene */
/* note: now unlinks constraints as well */
-void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
+void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
{
- if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
- ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0)
+ if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
+ ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
{
/* We cannot delete indirectly used object... */
printf("WARNING, undeletable object '%s', should have been catched before reaching this function!",
- base->object->id.name + 2);
+ ob->id.name + 2);
return;
}
- BKE_scene_base_unlink(scene, base);
- object_delete_check_glsl_update(base->object);
- BKE_libblock_free_us(bmain, base->object);
- MEM_freeN(base);
+ object_delete_check_glsl_update(ob);
+ BKE_collections_object_remove(bmain, scene, ob, true);
DAG_id_type_tag(bmain, ID_OB);
}
@@ -1139,56 +1139,46 @@ static int object_delete_exec(bContext *C, wmOperator *op)
if (CTX_data_edit_object(C))
return OPERATOR_CANCELLED;
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
- const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, base->object);
- if (base->object->id.tag & LIB_TAG_INDIRECT) {
+ const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
+ if (ob->id.tag & LIB_TAG_INDIRECT) {
/* Can this case ever happen? */
- BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
+ BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
continue;
}
- else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
+ else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
BKE_reportf(op->reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- base->object->id.name + 2, scene->id.name + 2);
+ ob->id.name + 2, scene->id.name + 2);
continue;
}
/* remove from Grease Pencil parent */
for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl->parent != NULL) {
- Object *ob = gpl->parent;
- Object *curob = base->object;
- if (ob == curob) {
+ if (gpl->parent == ob) {
gpl->parent = NULL;
}
}
}
}
- /* deselect object -- it could be used in other scenes */
- base->object->flag &= ~SELECT;
-
/* remove from current scene only */
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, ob);
changed = true;
if (use_global) {
Scene *scene_iter;
- Base *base_other;
-
for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) {
if (scene_iter != scene && !ID_IS_LINKED_DATABLOCK(scene_iter)) {
- base_other = BKE_scene_base_find(scene_iter, base->object);
- if (base_other) {
- if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- base->object->id.name + 2, scene_iter->id.name + 2);
- break;
- }
- ED_base_object_free_and_unlink(bmain, scene_iter, base_other);
+ if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
+ ob->id.name + 2, scene_iter->id.name + 2);
+ break;
}
+ ED_base_object_free_and_unlink(bmain, scene_iter, ob);
}
}
}
@@ -1329,6 +1319,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_hierarchy)
{
Main *bmain = CTX_data_main(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ListBase *lb;
DupliObject *dob;
GHash *dupli_gh = NULL, *parent_gh = NULL;
@@ -1360,12 +1351,10 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
*/
if (ob->mat == NULL) ob->totcol = 0;
- basen = MEM_dupallocN(base);
- basen->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP);
- ob->flag = basen->flag;
- basen->lay = base->lay;
- BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
- basen->object = ob;
+ BKE_collection_object_add_from(scene, dob->ob, ob);
+ basen = BKE_scene_layer_base_find(sl, ob);
+
+ BKE_scene_object_base_flag_sync_from_base(basen);
/* make sure apply works */
BKE_animdata_free(&ob->id, true);
@@ -1380,7 +1369,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
BLI_listbase_clear(&ob->constraints);
ob->curve_cache = NULL;
ob->transflag &= ~OB_DUPLI;
- ob->lay = base->lay;
copy_m4_m4(ob->obmat, dob->mat);
BKE_object_apply_mat4(ob, ob->obmat, false, false);
@@ -1589,7 +1577,7 @@ static int convert_poll(bContext *C)
}
/* Helper for convert_exec */
-static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob)
+static Base *duplibase_for_convert(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, Object *ob)
{
Object *obn;
Base *basen;
@@ -1600,16 +1588,11 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object
obn = BKE_object_copy(bmain, ob);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ BKE_collection_object_add_from(scene, ob, obn);
- basen = MEM_mallocN(sizeof(Base), "duplibase");
- *basen = *base;
- BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
- basen->object = obn;
- basen->flag |= SELECT;
- obn->flag |= SELECT;
- base->flag &= ~SELECT;
- ob->flag &= ~SELECT;
-
+ basen = BKE_scene_layer_base_find(sl, obn);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_select(basen, BA_DESELECT);
return basen;
}
@@ -1617,6 +1600,7 @@ static int convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Base *basen = NULL, *basact = NULL;
Object *ob, *ob1, *newob, *obact = CTX_data_active_object(C);
DerivedMesh *dm;
@@ -1631,7 +1615,7 @@ static int convert_exec(bContext *C, wmOperator *op)
/* don't forget multiple users! */
{
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
ob = base->object;
@@ -1678,7 +1662,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1703,7 +1687,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1735,7 +1719,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1806,7 +1790,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (target == OB_MESH) {
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1841,7 +1825,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!(baseob->flag & OB_DONE)) {
baseob->flag |= OB_DONE;
- basen = duplibase_for_convert(bmain, scene, base, baseob);
+ basen = duplibase_for_convert(bmain, scene, sl, base, baseob);
newob = basen->object;
mb = newob->data;
@@ -1892,23 +1876,21 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!keep_original) {
if (mballConverted) {
- Base *base, *base_next;
-
- for (base = scene->base.first; base; base = base_next) {
- base_next = base->next;
-
- ob = base->object;
+ Object *ob_mball;
+ FOREACH_SCENE_OBJECT(scene, ob_mball)
+ {
if (ob->type == OB_MBALL) {
if (ob->flag & OB_DONE) {
Object *ob_basis = NULL;
- if (BKE_mball_is_basis(ob) ||
- ((ob_basis = BKE_mball_basis_find(scene, ob)) && (ob_basis->flag & OB_DONE)))
+ if (BKE_mball_is_basis(ob_mball) ||
+ ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
{
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, ob_mball);
}
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
/* delete object should renew depsgraph */
@@ -1920,12 +1902,12 @@ static int convert_exec(bContext *C, wmOperator *op)
if (basact) {
/* active base was changed */
- ED_base_object_activate(C, basact);
- BASACT = basact;
+ ED_object_base_activate(C, basact);
+ BASACT_NEW = basact;
}
- else if (BASACT->object->flag & OB_DONE) {
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT->object);
- WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT->object);
+ else if (BASACT_NEW->object->flag & OB_DONE) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT_NEW->object);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT_NEW->object);
}
DAG_relations_tag_update(bmain);
@@ -1967,18 +1949,17 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* used below, assumes id.new is correct */
/* leaves selection of base/object unaltered */
/* Does set ID->newid pointers. */
-static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag)
+static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, int dupflag)
{
#define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
#define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
Base *basen = NULL;
Material ***matarar;
- Object *ob, *obn;
+ Object *obn;
ID *id;
int a, didit;
- ob = base->object;
if (ob->mode & OB_MODE_POSE) {
; /* nothing? */
}
@@ -1986,20 +1967,18 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- basen = MEM_mallocN(sizeof(Base), "duplibase");
- *basen = *base;
- BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */
- basen->object = obn;
+ BKE_collection_object_add_from(scene, ob, obn);
+ basen = BKE_scene_layer_base_find(sl, obn);
/* 1) duplis should end up in same group as the original
* 2) Rigid Body sim participants MUST always be part of a group...
*/
// XXX: is 2) really a good measure here?
- if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) {
+ if ((ob->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) {
Group *group;
for (group = bmain->group.first; group; group = group->id.next) {
if (BKE_group_object_exists(group, ob))
- BKE_group_object_add(group, obn, scene, basen);
+ BKE_group_object_add(group, obn);
}
}
@@ -2207,14 +2186,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
* note: don't call this within a loop since clear_* funcs loop over the entire database.
* note: caller must do DAG_relations_tag_update(bmain);
* this is not done automatic since we may duplicate many objects in a batch */
-Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag)
+Base *ED_object_add_duplicate(Main *bmain, Scene *scene, SceneLayer *sl, Base *base, int dupflag)
{
Base *basen;
Object *ob;
clear_sca_new_poins(); /* BGE logic */
- basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+ basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag);
if (basen == NULL) {
return NULL;
}
@@ -2241,6 +2220,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
@@ -2248,19 +2228,19 @@ static int duplicate_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+ Base *basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag);
/* note that this is safe to do with this context iterator,
* the list is made in advance */
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
if (basen == NULL) {
continue;
}
/* new object becomes active */
- if (BASACT == base)
- ED_base_object_activate(C, basen);
+ if (BASACT_NEW == base)
+ ED_object_base_activate(C, basen);
if (basen->object->data) {
DAG_id_tag_update(basen->object->data, 0);
@@ -2308,9 +2288,9 @@ static int add_named_exec(bContext *C, wmOperator *op)
wmWindow *win = CTX_wm_window(C);
const wmEvent *event = win ? win->eventstate : NULL;
Main *bmain = CTX_data_main(C);
- View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
Scene *scene = CTX_data_scene(C);
- Base *basen, *base;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Base *basen;
Object *ob;
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
@@ -2325,22 +2305,17 @@ static int add_named_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- base = MEM_callocN(sizeof(Base), "duplibase");
- base->object = ob;
- base->flag = ob->flag;
-
/* prepare dupli */
clear_sca_new_poins(); /* BGE logic */
- basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+ basen = object_add_duplicate_internal(bmain, scene, sl, ob, dupflag);
+ BKE_scene_object_base_flag_sync_from_object(basen);
if (basen == NULL) {
- MEM_freeN(base);
BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
return OPERATOR_CANCELLED;
}
- basen->lay = basen->object->lay = BKE_screen_view3d_layer_active(v3d, scene);
basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
if (event) {
@@ -2351,8 +2326,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
ED_view3d_cursor3d_position(C, basen->object->loc, mval);
}
- ED_base_object_select(basen, BA_SELECT);
- ED_base_object_activate(C, basen);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_activate(C, basen);
copy_object_set_idnew(C);
@@ -2360,8 +2335,6 @@ static int add_named_exec(bContext *C, wmOperator *op)
DAG_relations_tag_update(bmain);
- MEM_freeN(base);
-
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 59d78f13ccb..2437a6bff28 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1682,14 +1682,15 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
if ((found == false) && (add)) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Base *base = BASACT, *newbase = NULL;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Base *base = BASACT_NEW, *newbase = NULL;
Object *obt;
/* add new target object */
- obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
+ obt = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL);
/* set layers OK */
- newbase = BASACT;
+ newbase = BASACT_NEW;
newbase->lay = base->lay;
obt->lay = newbase->lay;
@@ -1708,8 +1709,8 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob
}
/* restore, BKE_object_add sets active */
- BASACT = base;
- base->flag |= SELECT;
+ BASACT_NEW = base;
+ base->flag |= BASE_SELECTED;
/* make our new target the new object */
*tar_ob = obt;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index edd7b5dd1be..2a4557f3610 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -132,189 +132,6 @@ Object *ED_object_active_context(bContext *C)
}
-/* ********* clear/set restrict view *********/
-static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- Scene *scene = CTX_data_scene(C);
- Base *base;
- bool changed = false;
-
- /* XXX need a context loop to handle such cases */
- for (base = FIRSTBASE; base; base = base->next) {
- if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
- if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) {
- base->flag |= SELECT;
- }
- base->object->flag = base->flag;
- base->object->restrictflag &= ~OB_RESTRICT_VIEW;
- changed = true;
- }
- }
- if (changed) {
- DAG_id_type_tag(bmain, ID_OB);
- DAG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Clear Restrict View";
- ot->description = "Reveal the object by setting the hide flag";
- ot->idname = "OBJECT_OT_hide_view_clear";
-
- /* api callbacks */
- ot->exec = object_hide_view_clear_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int object_hide_view_set_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bool changed = false;
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
-
- CTX_DATA_BEGIN(C, Base *, base, visible_bases)
- {
- if (!unselected) {
- if (base->flag & SELECT) {
- base->flag &= ~SELECT;
- base->object->flag = base->flag;
- base->object->restrictflag |= OB_RESTRICT_VIEW;
- changed = true;
- if (base == BASACT) {
- ED_base_object_activate(C, NULL);
- }
- }
- }
- else {
- if (!(base->flag & SELECT)) {
- base->object->restrictflag |= OB_RESTRICT_VIEW;
- changed = true;
- if (base == BASACT) {
- ED_base_object_activate(C, NULL);
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (changed) {
- DAG_id_type_tag(bmain, ID_OB);
- DAG_relations_tag_update(bmain);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- }
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_view_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Restrict View";
- ot->description = "Hide the object by setting the hide flag";
- ot->idname = "OBJECT_OT_hide_view_set";
-
- /* api callbacks */
- ot->exec = object_hide_view_set_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
-
-}
-
-/* 99% same as above except no need for scene refreshing (TODO, update render preview) */
-static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bool changed = false;
-
- /* XXX need a context loop to handle such cases */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- if (ob->restrictflag & OB_RESTRICT_RENDER) {
- ob->restrictflag &= ~OB_RESTRICT_RENDER;
- changed = true;
- }
- }
- CTX_DATA_END;
-
- if (changed)
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_render_clear(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Clear Restrict Render";
- ot->description = "Reveal the render object by setting the hide render flag";
- ot->idname = "OBJECT_OT_hide_render_clear";
-
- /* api callbacks */
- ot->exec = object_hide_render_clear_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int object_hide_render_set_exec(bContext *C, wmOperator *op)
-{
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
-
- CTX_DATA_BEGIN(C, Base *, base, visible_bases)
- {
- if (!unselected) {
- if (base->flag & SELECT) {
- base->object->restrictflag |= OB_RESTRICT_RENDER;
- }
- }
- else {
- if (!(base->flag & SELECT)) {
- base->object->restrictflag |= OB_RESTRICT_RENDER;
- }
- }
- }
- CTX_DATA_END;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_render_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Restrict Render";
- ot->description = "Hide the render object by setting the hide render flag";
- ot->idname = "OBJECT_OT_hide_render_set";
-
- /* api callbacks */
- ot->exec = object_hide_render_set_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
-}
-
/* ******************* toggle editmode operator ***************** */
static bool mesh_needs_keyindex(const Mesh *me)
@@ -465,31 +282,22 @@ void ED_object_editmode_exit(bContext *C, int flag)
void ED_object_editmode_enter(bContext *C, int flag)
{
Scene *scene = CTX_data_scene(C);
- Base *base = NULL;
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob;
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = NULL;
bool ok = false;
if (ID_IS_LINKED_DATABLOCK(scene)) return;
- if (sa && sa->spacetype == SPACE_VIEW3D)
- v3d = sa->spacedata.first;
-
if ((flag & EM_IGNORE_LAYER) == 0) {
- base = CTX_data_active_base(C); /* active layer checked here for view3d */
+ ob = CTX_data_active_object(C); /* active layer checked here for view3d */
- if (base == NULL) return;
- else if (v3d && (base->lay & v3d->lay) == 0) return;
- else if (!v3d && (base->lay & scene->lay) == 0) return;
+ if (ob == NULL) return;
}
else {
- base = scene->basact;
+ ob = sl->basact->object;
}
- if (ELEM(NULL, base, base->object, base->object->data)) return;
-
- ob = base->object;
+ if (ELEM(NULL, ob, ob->data)) return;
/* this checks actual object->data, for cases when other scenes have it in editmode context */
if (BKE_object_is_in_editmode(ob))
@@ -698,7 +506,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
{
//XXX no longer used - to be removed - replaced by game_properties_copy_exec
bProperty *prop;
- Base *base;
+ BaseLegacy *base;
int nr, tot = 0;
char *str;
@@ -758,7 +566,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
{
//XXX no longer used - to be removed - replaced by logicbricks_copy_exec
- Base *base;
+ BaseLegacy *base;
for (base = FIRSTBASE; base; base = base->next) {
if (base->object != ob) {
@@ -844,7 +652,7 @@ static void copy_texture_space(Object *to, Object *ob)
static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
{
Object *ob;
- Base *base;
+ BaseLegacy *base;
Curve *cu, *cu1;
Nurb *nu;
bool do_depgraph_update = false;
@@ -1512,7 +1320,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
{
/* all selected objects with an image map: scale in image aspect */
- Base *base;
+ BaseLegacy *base;
Object *ob;
Material *ma;
Tex *tex;
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 0fe43c44d7d..b22b034ecab 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -128,7 +128,6 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -151,7 +150,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
continue;
if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
- BKE_group_object_add(group, base->object, scene, base);
+ BKE_group_object_add(group, base->object);
updated = true;
}
else {
@@ -200,8 +199,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot)
static int objects_remove_active_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -221,7 +220,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
/* Remove groups from selected objects */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object, scene, base);
+ BKE_group_object_unlink(group, base->object);
ok = 1;
}
CTX_DATA_END;
@@ -264,11 +263,10 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot)
static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_object_groups_clear(scene, base, base->object);
+ BKE_object_groups_clear(base->object);
}
CTX_DATA_END;
@@ -297,7 +295,6 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -315,7 +312,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
/* now remove all selected objects from the group */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object, scene, base);
+ BKE_group_object_unlink(group, base->object);
updated = true;
}
CTX_DATA_END;
@@ -357,7 +354,6 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
static int group_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Group *group = NULL;
char name[MAX_ID_NAME - 2]; /* id name */
@@ -367,7 +363,7 @@ static int group_create_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_group_object_add(group, base->object, scene, base);
+ BKE_group_object_add(group, base->object);
}
CTX_DATA_END;
@@ -398,7 +394,6 @@ void GROUP_OT_create(wmOperatorType *ot)
static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
Group *group;
@@ -407,7 +402,7 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
group = BKE_group_add(bmain, "Group");
- BKE_group_object_add(group, ob, scene, NULL);
+ BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -432,7 +427,6 @@ void OBJECT_OT_group_add(wmOperatorType *ot)
static int group_link_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group"));
@@ -457,7 +451,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_group_object_add(group, ob, scene, NULL);
+ BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -490,14 +484,13 @@ void OBJECT_OT_group_link(wmOperatorType *ot)
static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
if (!ob || !group)
return OPERATOR_CANCELLED;
- BKE_group_object_unlink(group, ob, scene, NULL); /* base will be used if found */
+ BKE_group_object_unlink(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -560,8 +553,10 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (BKE_group_object_exists(group, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 438c10c51fa..f41f21f5bd4 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -445,12 +445,12 @@ static int hook_op_edit_poll(bContext *C)
return 0;
}
-static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit)
+static Object *add_hook_object_new(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit)
{
- Base *base, *basedit;
+ BaseLegacy *base, *basedit;
Object *ob;
- ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
+ ob = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL);
basedit = BKE_scene_base_find(scene, obedit);
base = scene->basact;
@@ -464,7 +464,7 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit)
return ob;
}
-static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode, ReportList *reports)
+static int add_hook_object(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit, Object *ob, int mode, ReportList *reports)
{
ModifierData *md = NULL;
HookModifierData *hmd = NULL;
@@ -482,7 +482,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
- ob = add_hook_object_new(bmain, scene, obedit);
+ ob = add_hook_object_new(bmain, scene, sl, obedit);
/* transform cent to global coords for loc */
mul_v3_m4v3(ob->loc, obedit->obmat, cent);
@@ -556,6 +556,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
Object *obsel = NULL;
const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
@@ -580,7 +581,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (add_hook_object(bmain, scene, obedit, obsel, mode, op->reports)) {
+ if (add_hook_object(bmain, scene, sl, obedit, obsel, mode, op->reports)) {
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;
}
@@ -611,9 +612,10 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
- if (add_hook_object(bmain, scene, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
+ if (add_hook_object(bmain, scene, sl, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 9710e4f843d..fe0ceb15d70 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -70,7 +70,6 @@ void OBJECT_OT_make_local(struct wmOperatorType *ot);
void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
-void OBJECT_OT_move_to_layer(struct wmOperatorType *ot);
void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
@@ -78,10 +77,6 @@ void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
void OBJECT_OT_mode_set(struct wmOperatorType *ot);
void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot);
void OBJECT_OT_posemode_toggle(struct wmOperatorType *ot);
-void OBJECT_OT_hide_view_set(struct wmOperatorType *ot);
-void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot);
-void OBJECT_OT_hide_render_set(struct wmOperatorType *ot);
-void OBJECT_OT_hide_render_clear(struct wmOperatorType *ot);
void OBJECT_OT_proxy_make(struct wmOperatorType *ot);
void OBJECT_OT_shade_smooth(struct wmOperatorType *ot);
void OBJECT_OT_shade_flat(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 06f495fb9f1..bca7a163e90 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -411,7 +411,7 @@ 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)
+int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, ModifierData *md)
{
Object *obn;
ParticleSystem *psys;
@@ -463,7 +463,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
if (totvert == 0) return 0;
/* add new mesh */
- obn = BKE_object_add(bmain, scene, OB_MESH, NULL);
+ obn = BKE_object_add(bmain, scene, sl, OB_MESH, NULL);
me = obn->data;
me->totvert = totvert;
@@ -1048,10 +1048,11 @@ static int modifier_convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(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))
+ if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, sl, ob, md))
return OPERATOR_CANCELLED;
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -1683,7 +1684,7 @@ static void skin_armature_bone_create(Object *skin_ob,
}
}
-static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *skin_ob)
+static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, SceneLayer *sl, Object *skin_ob)
{
BLI_bitmap *edges_visited;
DerivedMesh *deform_dm;
@@ -1706,7 +1707,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *
NULL,
me->totvert);
- arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL);
+ arm_ob = BKE_object_add(bmain, scene, sl, OB_ARMATURE, NULL);
BKE_object_transform_copy(arm_ob, skin_ob);
arm = arm_ob->data;
arm->layer = 1;
@@ -1765,6 +1766,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = CTX_data_active_object(C), *arm_ob;
Mesh *me = ob->data;
ModifierData *skin_md;
@@ -1776,7 +1778,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
}
/* create new armature */
- arm_ob = modifier_skin_armature_create(bmain, scene, ob);
+ arm_ob = modifier_skin_armature_create(bmain, scene, sl, ob);
/* add a modifier to connect the new armature to the mesh */
arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 7e7e1ef182c..19526db2ce8 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -67,10 +67,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_editmode_toggle);
WM_operatortype_append(OBJECT_OT_posemode_toggle);
WM_operatortype_append(OBJECT_OT_proxy_make);
- WM_operatortype_append(OBJECT_OT_hide_view_clear);
- WM_operatortype_append(OBJECT_OT_hide_view_set);
- WM_operatortype_append(OBJECT_OT_hide_render_clear);
- WM_operatortype_append(OBJECT_OT_hide_render_set);
WM_operatortype_append(OBJECT_OT_shade_smooth);
WM_operatortype_append(OBJECT_OT_shade_flat);
WM_operatortype_append(OBJECT_OT_paths_calculate);
@@ -90,13 +86,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_make_single_user);
WM_operatortype_append(OBJECT_OT_make_links_scene);
WM_operatortype_append(OBJECT_OT_make_links_data);
- WM_operatortype_append(OBJECT_OT_move_to_layer);
WM_operatortype_append(OBJECT_OT_select_random);
WM_operatortype_append(OBJECT_OT_select_all);
WM_operatortype_append(OBJECT_OT_select_same_group);
WM_operatortype_append(OBJECT_OT_select_by_type);
- WM_operatortype_append(OBJECT_OT_select_by_layer);
WM_operatortype_append(OBJECT_OT_select_linked);
WM_operatortype_append(OBJECT_OT_select_grouped);
WM_operatortype_append(OBJECT_OT_select_mirror);
@@ -382,25 +376,6 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "unselected", false);
-
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "unselected", true);
-
- /* same as above but for rendering */
- WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_clear", HKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
- WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_CTRL, 0);
-
- /* conflicts, removing */
-#if 0
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0)
- RNA_boolean_set(kmi->ptr, "unselected", true);
-#endif
-
- WM_keymap_add_item(keymap, "OBJECT_OT_move_to_layer", MKEY, KM_PRESS, 0, 0);
-
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_global", false);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index d30022c01f8..c79c702837a 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -63,6 +63,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
@@ -74,6 +75,7 @@
#include "BKE_fcurve.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -331,6 +333,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
Object *ob, *gob = ED_object_active_context(C);
GroupObject *go;
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
if (gob->dup_group != NULL) {
go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object"));
@@ -343,13 +346,13 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
if (ob) {
Object *newob;
- Base *newbase, *oldbase = BASACT;
+ BaseLegacy *newbase, *oldbase = BASACT;
char name[MAX_ID_NAME + 4];
BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
/* Add new object for the proxy */
- newob = BKE_object_add(bmain, scene, OB_EMPTY, name);
+ newob = BKE_object_add(bmain, scene, sl, OB_EMPTY, name);
/* set layers OK */
newbase = BASACT; /* BKE_object_add sets active... */
@@ -1305,119 +1308,6 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
-/************************** Move to Layer Operator *****************************/
-
-static unsigned int move_to_layer_init(bContext *C, wmOperator *op)
-{
- int values[20], a;
- unsigned int lay = 0;
-
- if (!RNA_struct_property_is_set(op->ptr, "layers")) {
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- lay |= base->lay;
- }
- CTX_DATA_END;
-
- for (a = 0; a < 20; a++)
- values[a] = (lay & (1 << a)) != 0;
-
- RNA_boolean_set_array(op->ptr, "layers", values);
- }
- else {
- RNA_boolean_get_array(op->ptr, "layers", values);
-
- for (a = 0; a < 20; a++)
- if (values[a])
- lay |= (1 << a);
- }
-
- return lay;
-}
-
-static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d && v3d->localvd) {
- return WM_operator_confirm_message(C, op, "Move out of Local View");
- }
- else {
- move_to_layer_init(C, op);
- return WM_operator_props_popup(C, op, event);
- }
-}
-
-static int move_to_layer_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- unsigned int lay, local;
- /* bool is_lamp = false; */ /* UNUSED */
-
- lay = move_to_layer_init(C, op);
- lay &= 0xFFFFFF;
-
- if (lay == 0) return OPERATOR_CANCELLED;
-
- if (v3d && v3d->localvd) {
- /* now we can move out of localview. */
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- lay = base->lay & ~v3d->lay;
- base->lay = lay;
- base->object->lay = lay;
- base->object->flag &= ~SELECT;
- base->flag &= ~SELECT;
- /* if (base->object->type == OB_LAMP) is_lamp = true; */
- }
- CTX_DATA_END;
- }
- else {
- /* normal non localview operation */
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- /* upper byte is used for local view */
- local = base->lay & 0xFF000000;
- base->lay = lay + local;
- base->object->lay = base->lay;
- /* if (base->object->type == OB_LAMP) is_lamp = true; */
- }
- CTX_DATA_END;
- }
-
- /* warning, active object may be hidden now */
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
-
- DAG_relations_tag_update(bmain);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_move_to_layer(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move to Layer";
- ot->description = "Move the object to different layers";
- ot->idname = "OBJECT_OT_move_to_layer";
-
- /* api callbacks */
- ot->invoke = move_to_layer_invoke;
- ot->exec = move_to_layer_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", "");
-}
-
/************************** Link to Scene Operator *****************************/
#if 0
@@ -1440,20 +1330,6 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
}
#endif
-Base *ED_object_scene_link(Scene *scene, Object *ob)
-{
- Base *base;
-
- if (BKE_scene_base_find(scene, ob)) {
- return NULL;
- }
-
- base = BKE_scene_base_add(scene, ob);
- id_us_plus(&ob->id);
-
- return base;
-}
-
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
@@ -1473,9 +1349,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ SceneCollection *sc_to = BKE_collection_master(scene_to);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- ED_object_scene_link(scene_to, base->object);
+ BKE_collection_object_add(scene_to, sc_to, base->object);
}
CTX_DATA_END;
@@ -1531,7 +1408,6 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
static int make_links_data_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
const int type = RNA_enum_get(op->ptr, "type");
Object *ob_src;
ID *obdata_id;
@@ -1594,12 +1470,12 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
LinkNode *group_node;
/* first clear groups */
- BKE_object_groups_clear(scene, base_dst, ob_dst);
+ BKE_object_groups_clear(ob_dst);
/* now add in the groups from the link nodes */
for (group_node = ob_groups; group_node; group_node = group_node->next) {
if (ob_dst->dup_group != group_node->link) {
- BKE_group_object_add(group_node->link, ob_dst, scene, base_dst);
+ BKE_group_object_add(group_node->link, ob_dst);
}
else {
is_cycle = true;
@@ -1732,48 +1608,82 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
+static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
+{
+ if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) {
+ /* base gets copy of object */
+ Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
+
+ if (copy_groups) {
+ if (ob->flag & OB_FROMGROUP) {
+ obn->flag |= OB_FROMGROUP;
+ }
+ }
+ else {
+ /* copy already clears */
+ }
+ /* remap gpencil parenting */
+
+ if (scene->gpd) {
+ bGPdata *gpd = scene->gpd;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent == ob) {
+ gpl->parent = obn;
+ }
+ }
+ }
+
+ id_us_min(&ob->id);
+ return obn;
+ }
+ return NULL;
+}
+
+static void libblock_relink_scene_collection(SceneCollection *sc)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ BKE_libblock_relink_to_newid(link->data);
+ }
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ libblock_relink_scene_collection(nsc);
+ }
+}
+
+static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ Object *ob = link->data;
+ /* an object may be in more than one collection */
+ if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
+ link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
+ }
+ }
+
+ /* we reset filter objects because they should be regenerated after this */
+ BLI_freelistN(&sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups);
+ }
+}
+
/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
{
- Base *base;
- Object *ob, *obn;
Group *group, *groupn;
GroupObject *go;
clear_sca_new_poins(); /* BGE logic */
- /* duplicate (must set newid) */
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
-
- if ((base->flag & flag) == flag) {
- if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) {
- /* base gets copy of object */
- base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
-
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
- }
- /* remap gpencil parenting */
-
- if (scene->gpd) {
- bGPdata *gpd = scene->gpd;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent == ob) {
- gpl->parent = obn;
- }
- }
- }
-
- base->flag = obn->flag;
+ /* duplicate all the objects of the scene */
+ SceneCollection *msc = BKE_collection_master(scene);
+ single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups);
- id_us_min(&ob->id);
- }
+ /* loop over SceneLayers and assign the pointers accordingly */
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ ID_NEW_REMAP(base->object);
}
}
@@ -1806,27 +1716,29 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
if (v3d) ID_NEW_REMAP(v3d->camera);
/* object and group pointers */
- for (base = FIRSTBASE; base; base = base->next) {
- BKE_libblock_relink_to_newid(&base->object->id);
- }
+ libblock_relink_scene_collection(msc);
set_sca_new_poins();
+
+ /* TODO redo filter */
+ TODO_LAYER_SYNC_FILTER
}
/* not an especially efficient function, only added so the single user
* button can be functional.*/
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
- Base *base;
- const bool copy_groups = false;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->object == ob) base->flag |= OB_DONE;
- else base->flag &= ~OB_DONE;
+ Object *ob_iter;
+ FOREACH_SCENE_OBJECT(scene, ob_iter)
+ {
+ ob_iter->flag &= ~OB_DONE;
}
+ FOREACH_SCENE_OBJECT_END
- single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
+ /* tag only the one object */
+ ob->flag |= OB_DONE;
+ single_object_users(bmain, scene, NULL, OB_DONE, false);
BKE_main_id_clear_newpoins(bmain);
}
@@ -1857,15 +1769,17 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
Lamp *la;
Curve *cu;
/* Camera *cam; */
- Base *base;
+ BaseLegacy *base;
Mesh *me;
Lattice *lat;
ID *id;
int a;
+ TODO_LAYER; /* need to use scene->collection base instead of scene->bases */
+
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
- if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag & flag) == flag) {
+ if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag_legacy & flag) == flag) {
id = ob->data;
if (id && id->us > 1 && !ID_IS_LINKED_DATABLOCK(id)) {
@@ -1939,31 +1853,27 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
}
}
-static void single_object_action_users(Scene *scene, const int flag)
+static void single_object_action_users(Scene *scene, SceneLayer *sl, const int flag)
{
Object *ob;
- Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) {
+ FOREACH_OBJECT_FLAG(scene, sl, flag, ob)
+ if (!ID_IS_LINKED_DATABLOCK(ob)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_animdata_copy_id_action(&ob->id, false);
}
- }
+ FOREACH_OBJECT_FLAG_END
}
-static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bool do_textures)
+static void single_mat_users(Main *bmain, Scene *scene, SceneLayer *sl, const int flag, const bool do_textures)
{
- Object *ob;
- Base *base;
Material *ma, *man;
Tex *tex;
int a, b;
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) {
+ Object *ob;
+ FOREACH_OBJECT_FLAG(scene, sl, flag, ob)
+ if (!ID_IS_LINKED_DATABLOCK(ob)) {
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
if (ma) {
@@ -1992,7 +1902,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
}
}
}
- }
+ FOREACH_OBJECT_FLAG_END
}
static void do_single_tex_user(Main *bmain, Tex **from)
@@ -2096,7 +2006,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
if (full) {
single_obdata_users(bmain, scene, 0);
- single_object_action_users(scene, 0);
+ single_object_action_users(scene, NULL, 0);
single_mat_users_expand(bmain);
single_tex_users_expand(bmain);
}
@@ -2133,7 +2043,7 @@ enum {
};
static int tag_localizable_looper(
- void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cd_flag))
+ void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cb_flag))
{
if (*id_pointer) {
(*id_pointer)->tag &= ~LIB_TAG_DOIT;
@@ -2170,12 +2080,12 @@ static void tag_localizable_objects(bContext *C, const int mode)
*/
for (Object *object = bmain->object.first; object; object = object->id.next) {
if ((object->id.tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(&object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ BKE_library_foreach_ID_link(NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
}
if (object->data) {
ID *data_id = (ID *) object->data;
if ((data_id->tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
}
}
}
@@ -2194,13 +2104,13 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ID_IS_LINKED_DATABLOCK(ob) && (ob->id.us == 0)) {
- Base *base;
+ BaseLegacy *base;
id_us_plus(&ob->id);
base = BKE_scene_base_add(scene, ob);
- base->flag |= SELECT;
- base->object->flag = base->flag;
+ base->flag_legacy |= SELECT;
+ BKE_scene_base_flag_sync_from_base(base);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
changed = true;
@@ -2366,13 +2276,20 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
const bool copy_groups = false;
bool update_deps = false;
if (RNA_boolean_get(op->ptr, "object")) {
- single_object_users(bmain, scene, v3d, flag, copy_groups);
+ if (flag == SELECT) {
+ BKE_scene_layer_selected_objects_tag(sl, OB_DONE);
+ single_object_users(bmain, scene, v3d, OB_DONE, copy_groups);
+ }
+ else {
+ single_object_users(bmain, scene, v3d, 0, copy_groups);
+ }
/* needed since object relationships may have changed */
update_deps = true;
@@ -2383,7 +2300,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "material")) {
- single_mat_users(bmain, scene, flag, RNA_boolean_get(op->ptr, "texture"));
+ single_mat_users(bmain, scene, sl, flag, RNA_boolean_get(op->ptr, "texture"));
}
#if 0 /* can't do this separate from materials */
@@ -2391,7 +2308,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
single_mat_users(scene, flag, true);
#endif
if (RNA_boolean_get(op->ptr, "animation")) {
- single_object_action_users(scene, flag);
+ single_object_action_users(scene, sl, flag);
}
BKE_main_id_clear_newpoins(bmain);
@@ -2438,7 +2355,7 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval);
Material *ma;
char name[MAX_ID_NAME - 2];
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index b5131df3eaa..37232456f48 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -52,6 +52,7 @@
#include "BKE_context.h"
#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_particle.h"
@@ -86,22 +87,22 @@
/* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! (or
* or a NC_SCENE|ND_OB_VISIBLE in case of visibility toggling */
-void ED_base_object_select(Base *base, short mode)
+void ED_base_object_select(BaseLegacy *base, short mode)
{
if (base) {
if (mode == BA_SELECT) {
if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
- base->flag |= SELECT;
+ base->flag_legacy |= SELECT;
}
else if (mode == BA_DESELECT) {
- base->flag &= ~SELECT;
+ base->flag_legacy &= ~SELECT;
}
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
}
}
/* also to set active NULL */
-void ED_base_object_activate(bContext *C, Base *base)
+void ED_base_object_activate(bContext *C, BaseLegacy *base)
{
Scene *scene = CTX_data_scene(C);
@@ -119,6 +120,33 @@ void ED_base_object_activate(bContext *C, Base *base)
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
}
+void ED_object_base_select(Base *base, short mode)
+{
+ if (base) {
+ if (mode == BA_SELECT) {
+ if ((base->flag & BASE_SELECTABLED) != 0) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+ else if (mode == BA_DESELECT) {
+ base->flag &= ~BASE_SELECTED;
+ }
+ }
+}
+
+void ED_object_base_activate(bContext *C, Base *base)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ sl->basact = base;
+
+ if (base) {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, sl);
+ }
+ else {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
+ }
+}
+
/********************** Selection Operators **********************/
static int objects_selectable_poll(bContext *C)
@@ -147,7 +175,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
}
CTX_DATA_END;
}
@@ -155,7 +183,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (base->object->type == obtype) {
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
}
}
CTX_DATA_END;
@@ -210,38 +238,15 @@ static EnumPropertyItem prop_select_linked_types[] = {
{0, NULL, 0, NULL, NULL}
};
-// XXX old animation system
-#if 0
-static int object_select_all_by_ipo(bContext *C, Ipo *ipo)
-{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (base->object->ipo == ipo) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
- changed = true;
- }
- }
- CTX_DATA_END;
-
- return changed;
-}
-#endif
-
static bool object_select_all_by_obdata(bContext *C, void *obdata)
{
bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (base->object->data == obdata) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -257,7 +262,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
Object *ob = base->object;
Material *mat1;
int a, b;
@@ -267,7 +272,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
if (!use_texture) {
if (mat1 == mat) {
- base->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -275,7 +280,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
for (b = 0; b < MAX_MTEX; b++) {
if (mat1->mtex[b]) {
if (tex == mat1->mtex[b]->tex) {
- base->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
@@ -283,8 +288,6 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
}
}
}
-
- base->object->flag = base->flag;
}
}
CTX_DATA_END;
@@ -299,12 +302,10 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
if (dup_group == dup_group_other) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -321,23 +322,21 @@ static bool object_select_all_by_particle(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 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;
+ ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
- if (base->flag & SELECT) {
+ if (base->flag & BASE_SELECTED) {
break;
}
}
-
- base->object->flag = base->flag;
}
}
CTX_DATA_END;
@@ -351,11 +350,9 @@ static bool object_select_all_by_library(bContext *C, Library *lib)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (lib == base->object->id.lib) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -371,11 +368,9 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (base->object->data && lib == ((ID *)base->object->data)->lib) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -408,6 +403,7 @@ void ED_object_select_linked_by_id(bContext *C, ID *id)
static int object_select_linked_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob;
int nr = RNA_enum_get(op->ptr, "type");
bool changed = false, extend;
@@ -417,12 +413,12 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
}
CTX_DATA_END;
}
- ob = OBACT;
+ ob = OBACT_NEW;
if (ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active object");
return OPERATOR_CANCELLED;
@@ -517,7 +513,7 @@ enum {
OBJECT_GRPSEL_PARENT = 2,
OBJECT_GRPSEL_SIBLINGS = 3,
OBJECT_GRPSEL_TYPE = 4,
- OBJECT_GRPSEL_LAYER = 5,
+ /*OBJECT_GRPSEL_LAYER = 5,*/
OBJECT_GRPSEL_GROUP = 6,
OBJECT_GRPSEL_HOOK = 7,
OBJECT_GRPSEL_PASS = 8,
@@ -533,7 +529,6 @@ static EnumPropertyItem prop_select_grouped_types[] = {
{OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
{OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
{OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
- {OBJECT_GRPSEL_LAYER, "LAYER", 0, "Layer", "Shared layers"},
{OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"},
{OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
{OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
@@ -551,13 +546,14 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if (ob == base->object->parent) {
- if (!(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
- if (recursive)
+ if (recursive) {
changed |= select_grouped_children(C, base->object, 1);
+ }
}
}
CTX_DATA_END;
@@ -566,20 +562,21 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv
static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
{
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C);
-
- bool changed = false;
Base *baspar, *basact = CTX_data_active_base(C);
+ bool changed = false;
- if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
+ if (!basact || !(basact->object->parent)) {
+ return 0; /* we know OBACT is valid */
+ }
- baspar = BKE_scene_base_find(scene, basact->object->parent);
+ baspar = BKE_scene_layer_base_find(sl, basact->object->parent);
/* can be NULL if parent in other scene */
if (baspar && BASE_SELECTABLE(v3d, baspar)) {
- ED_base_object_select(baspar, BA_SELECT);
- ED_base_object_activate(C, baspar);
+ ED_object_base_select(baspar, BA_SELECT);
+ ED_object_base_activate(C, baspar);
changed = true;
}
return changed;
@@ -608,9 +605,11 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
group = ob_groups[0];
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
- ED_base_object_select(base, BA_SELECT);
- changed = true;
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (BKE_group_object_exists(group, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
}
}
CTX_DATA_END;
@@ -636,7 +635,7 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob)
View3D *v3d = CTX_wm_view3d(C);
bool changed = false;
- Base *base;
+ BaseLegacy *base;
ModifierData *md;
HookModifierData *hmd;
@@ -663,8 +662,8 @@ static bool select_grouped_siblings(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if ((base->object->parent == ob->parent) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -681,8 +680,8 @@ static bool select_grouped_lamptype(bContext *C, Object *ob)
{
if (base->object->type == OB_LAMP) {
Lamp *la_test = base->object->data;
- if ((la->type == la_test->type) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -696,23 +695,8 @@ static bool select_grouped_type(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
-}
-
-static bool select_grouped_layer(bContext *C, Object *ob)
-{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -726,8 +710,8 @@ static bool select_grouped_index_object(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -741,8 +725,8 @@ static bool select_grouped_color(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -768,8 +752,8 @@ static bool select_grouped_gameprops(bContext *C, Object *ob)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && (objects_share_gameprop(base->object, ob))) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -807,7 +791,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
/* only check for this object if it isn't selected already, to limit time wasted */
- if ((base->flag & SELECT) == 0) {
+ if ((base->flag & BASE_SELECTED) == 0) {
KS_Path *ksp;
/* this is the slow way... we could end up with > 500 items here,
@@ -816,7 +800,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
/* if id matches, select then stop looping (match found) */
if (ksp->id == (ID *)base->object) {
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
@@ -831,6 +815,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
static int object_select_grouped_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob;
const int type = RNA_enum_get(op->ptr, "type");
bool changed = false, extend;
@@ -840,13 +825,13 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
if (extend == 0) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
changed = true;
}
CTX_DATA_END;
}
- ob = OBACT;
+ ob = OBACT_NEW;
if (ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active object");
return OPERATOR_CANCELLED;
@@ -868,9 +853,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
case OBJECT_GRPSEL_TYPE:
changed |= select_grouped_type(C, ob);
break;
- case OBJECT_GRPSEL_LAYER:
- changed |= select_grouped_layer(C, ob);
- break;
case OBJECT_GRPSEL_GROUP:
changed |= select_grouped_group(C, ob);
break;
@@ -928,85 +910,6 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
}
-/************************* Select by Layer **********************/
-enum {
- OB_SEL_LAYERMATCH_EXACT = 1,
- OB_SEL_LAYERMATCH_SHARED = 2,
-};
-
-static int object_select_by_layer_exec(bContext *C, wmOperator *op)
-{
- unsigned int layernum;
- bool extend;
- int match;
-
- extend = RNA_boolean_get(op->ptr, "extend");
- layernum = RNA_int_get(op->ptr, "layers");
- match = RNA_enum_get(op->ptr, "match");
-
- if (extend == false) {
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- ED_base_object_select(base, BA_DESELECT);
- }
- CTX_DATA_END;
- }
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- bool ok = false;
-
- switch (match) {
- case OB_SEL_LAYERMATCH_EXACT:
- /* Mask out bits used for local view, only work on real layer ones, see T45783. */
- ok = ((base->lay & ((1 << 20) - 1)) == (1 << (layernum - 1)));
- break;
- case OB_SEL_LAYERMATCH_SHARED:
- ok = (base->lay & (1 << (layernum - 1))) != 0;
- break;
- default:
- break;
- }
-
- if (ok) {
- ED_base_object_select(base, BA_SELECT);
- }
- }
- CTX_DATA_END;
-
- /* undo? */
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_select_by_layer(wmOperatorType *ot)
-{
- static EnumPropertyItem match_items[] = {
- {OB_SEL_LAYERMATCH_EXACT, "EXACT", 0, "Exact Match", ""},
- {OB_SEL_LAYERMATCH_SHARED, "SHARED", 0, "Shared Layers", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Select by Layer";
- ot->description = "Select all visible objects on a layer";
- ot->idname = "OBJECT_OT_select_by_layer";
-
- /* api callbacks */
- /*ot->invoke = XXX - need a int grid popup*/
- ot->exec = object_select_by_layer_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "match", match_items, OB_SEL_LAYERMATCH_EXACT, "Match", "");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20);
-}
-
/**************************** (De)select All ****************************/
static int object_select_all_exec(bContext *C, wmOperator *op)
@@ -1020,7 +923,7 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
action = SEL_SELECT;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (base->flag & SELECT) {
+ if ((base->flag & BASE_SELECTED) != 0) {
action = SEL_DESELECT;
break;
}
@@ -1032,17 +935,17 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
{
switch (action) {
case SEL_SELECT:
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
break;
case SEL_DESELECT:
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
break;
case SEL_INVERT:
- if (base->flag & SELECT) {
- ED_base_object_select(base, BA_DESELECT);
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
}
else {
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
}
break;
}
@@ -1092,8 +995,11 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object))
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (BKE_group_object_exists(group, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
}
CTX_DATA_END;
@@ -1124,6 +1030,7 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot)
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
bool extend;
extend = RNA_boolean_get(op->ptr, "extend");
@@ -1137,15 +1044,15 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op)
if (!STREQ(name_flip, primbase->object->id.name + 2)) {
Object *ob = (Object *)BKE_libblock_find_name(ID_OB, name_flip);
if (ob) {
- Base *secbase = BKE_scene_base_find(scene, ob);
+ Base *secbase = BKE_scene_layer_base_find(sl, ob);
if (secbase) {
- ED_base_object_select(secbase, BA_SELECT);
+ ED_object_base_select(secbase, BA_SELECT);
}
}
}
- if (extend == false) ED_base_object_select(primbase, BA_DESELECT);
+ if (extend == false) ED_object_base_select(primbase, BA_DESELECT);
}
CTX_DATA_END;
@@ -1180,9 +1087,9 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
static bool object_select_more_less(bContext *C, const bool select)
{
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = sl->object_bases.first; base; base = base->next) {
Object *ob = base->object;
ob->flag &= ~OB_DONE;
ob->id.tag &= ~LIB_TAG_DOIT;
@@ -1223,7 +1130,7 @@ static bool object_select_more_less(bContext *C, const bool select)
Base *base = ctx_base->ptr.data;
Object *ob = base->object;
if ((ob->id.tag & LIB_TAG_DOIT) && ((ob->flag & SELECT) != select_flag)) {
- ED_base_object_select(base, select_mode);
+ ED_object_base_select(base, select_mode);
changed = true;
}
}
@@ -1305,7 +1212,7 @@ static int object_select_random_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if (BLI_rng_get_float(rng) < randfac) {
- ED_base_object_select(base, select);
+ ED_object_base_select(base, select);
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 56f59dca9a1..67ef4515c18 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -363,8 +363,8 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot
/* matching index only */
bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
{
- MDeformVert **dvert_array_from, **dvf;
- MDeformVert **dvert_array, **dv;
+ MDeformVert **dvert_array_from = NULL, **dvf;
+ MDeformVert **dvert_array = NULL, **dv;
int dvert_tot_from;
int dvert_tot;
int i;
@@ -375,26 +375,30 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
if (ob == ob_from)
return true;
- ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
-
- if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
+ /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */
+ if (ob->data != ob_from->data) {
+ ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- new_vgroup = true;
- }
- if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) {
+ if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+ new_vgroup = true;
+ }
- if (dvert_array) MEM_freeN(dvert_array);
- if (dvert_array_from) MEM_freeN(dvert_array_from);
+ if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) {
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+ if (dvert_array_from)
+ MEM_freeN(dvert_array_from);
- if (new_vgroup == true) {
- /* free the newly added vgroup since it wasn't compatible */
- BKE_object_defgroup_remove_all(ob);
- }
+ if (new_vgroup == true) {
+ /* free the newly added vgroup since it wasn't compatible */
+ BKE_object_defgroup_remove_all(ob);
+ }
- /* if true: both are 0 and nothing needs changing, consider this a success */
- return (dvert_tot == dvert_tot_from);
+ /* if true: both are 0 and nothing needs changing, consider this a success */
+ return (dvert_tot == dvert_tot_from);
+ }
}
/* do the copy */
@@ -412,22 +416,23 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
MEM_freeN(remap);
}
- dvf = dvert_array_from;
- dv = dvert_array;
+ if (dvert_array_from != NULL && dvert_array != NULL) {
+ dvf = dvert_array_from;
+ dv = dvert_array;
- for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
- if ((*dv)->dw)
- MEM_freeN((*dv)->dw);
+ for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
+ MEM_SAFE_FREE((*dv)->dw);
+ *(*dv) = *(*dvf);
- *(*dv) = *(*dvf);
+ if ((*dv)->dw) {
+ (*dv)->dw = MEM_dupallocN((*dv)->dw);
+ }
+ }
- if ((*dv)->dw)
- (*dv)->dw = MEM_dupallocN((*dv)->dw);
+ MEM_freeN(dvert_array);
+ MEM_freeN(dvert_array_from);
}
- MEM_freeN(dvert_array);
- MEM_freeN(dvert_array_from);
-
return true;
}
@@ -3296,7 +3301,7 @@ static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
- Base *base;
+ BaseLegacy *base;
int retval = OPERATOR_CANCELLED;
for (base = scene->base.first; base; base = base->next) {
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index b5adf38527b..bb3375b91a6 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -329,7 +329,7 @@ static void free_all_fluidobject_channels(ListBase *fobjects)
static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects)
{
Scene *scene = CTX_data_scene(C);
- Base *base;
+ BaseLegacy *base;
int i;
int length = channels->length;
float eval_time;
@@ -572,7 +572,7 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length)
static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDomain)
{
- Base *base;
+ BaseLegacy *base;
Object *newdomain = NULL;
int channelObjCount = 0;
int fluidInputCount = 0;
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index e81aa584586..4b19e235d9c 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -254,7 +254,7 @@ static void ptcache_bake_cancel(bContext *C, wmOperator *op)
static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
- Base *base;
+ BaseLegacy *base;
PTCacheID *pid;
ListBase pidlist;
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 1bfc162a331..b7be31602d9 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -89,7 +89,7 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type
ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
/* add constraint to rigid body constraint group */
- BKE_group_object_add(rbw->constraints, ob, scene, NULL);
+ BKE_group_object_add(rbw->constraints, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -102,7 +102,7 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_constraint(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->constraints, ob, scene, NULL);
+ BKE_group_object_unlink(rbw->constraints, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 30597d95497..c9e32fa5194 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -119,7 +119,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
- BKE_group_object_add(rbw->group, ob, scene, NULL);
+ BKE_group_object_add(rbw->group, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -133,7 +133,7 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_object(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->group, ob, scene, NULL);
+ BKE_group_object_unlink(rbw->group, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 8c5d25ad44d..07f4679a32a 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -784,7 +784,7 @@ static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay)
{
Object *object;
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
for (object = bmain->object.first; object; object = object->id.next) {
object->id.tag |= LIB_TAG_DOIT;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index c48e142f233..cb54f0efd85 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -276,7 +276,7 @@ static Scene *preview_get_scene(Main *pr_main)
static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
Scene *sce;
- Base *base;
+ BaseLegacy *base;
Main *pr_main = sp->pr_main;
memcpy(pr_main->name, bmain->name, sizeof(pr_main->name));
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 837573ad175..986e9623fef 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -54,6 +54,7 @@
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
@@ -626,11 +627,11 @@ static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- BKE_scene_add_render_layer(scene, NULL);
- scene->r.actlay = BLI_listbase_count(&scene->r.layers) - 1;
+ BKE_scene_layer_add(scene, NULL);
+ scene->active_layer = BLI_listbase_count(&scene->render_layers) - 1;
DAG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
return OPERATOR_FINISHED;
}
@@ -652,10 +653,11 @@ void SCENE_OT_render_layer_add(wmOperatorType *ot)
static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *rl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ SceneLayer *sl = BKE_scene_layer_active(scene);
- if (!BKE_scene_remove_render_layer(CTX_data_main(C), scene, rl))
+ if (!BKE_scene_layer_remove(CTX_data_main(C), scene, sl)) {
return OPERATOR_CANCELLED;
+ }
DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 7f91cd42d27..dbecbb974f7 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -373,41 +373,37 @@ static void region_draw_azone_tab_plus(AZone *az)
static void region_draw_azone_tab(AZone *az)
{
- float col[3];
+ float col[4], black[4] = {0.0f, 0.0f, 0.0f, 1.0f};
glEnable(GL_BLEND);
UI_GetThemeColor3fv(TH_HEADER, col);
- glColor4f(col[0], col[1], col[2], 0.5f);
-
+ col[3] = 0.5f;
+
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_RB_ALPHA);
- UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
- glColor4ub(0, 0, 0, 255);
- UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
+ UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f, black);
break;
case AE_BOTTOM_TO_TOPLEFT:
UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
- UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
- glColor4ub(0, 0, 0, 255);
- UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f);
+ UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_unfilled((float)az->x1, 0.3f + (float)az->y1, (float)az->x2, 0.3f + (float)az->y2, 4.0f, black);
break;
case AE_LEFT_TO_TOPRIGHT:
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT | UI_RB_ALPHA);
- UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
- glColor4ub(0, 0, 0, 255);
- UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
+ UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, black);
break;
case AE_RIGHT_TO_TOPLEFT:
UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_RB_ALPHA);
- UI_draw_roundbox_shade_x(GL_POLYGON, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f);
- glColor4ub(0, 0, 0, 255);
- UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
+ UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_unfilled((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, black);
break;
}
@@ -557,7 +553,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
UI_ThemeClearColor(TH_HEADER);
glClear(GL_COLOR_BUFFER_BIT);
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(BLF_default(), TH_TEXT);
BLF_draw_default(UI_UNIT_X, 0.4f * UI_UNIT_Y, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
}
else if (at->draw) {
@@ -2161,7 +2157,7 @@ void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], con
glDisable(GL_BLEND);
/* text */
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(fontid, TH_TEXT_HI);
BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
BLF_enable(fontid, BLF_CLIPPING);
BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit, 0.0f);
@@ -2369,7 +2365,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
BLF_enable(blf_mono_font, BLF_CLIPPING);
- UI_ThemeColor(TH_METADATA_TEXT);
+ UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true);
BLF_disable(blf_mono_font, BLF_CLIPPING);
@@ -2394,7 +2390,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
BLF_enable(blf_mono_font, BLF_CLIPPING);
- UI_ThemeColor(TH_METADATA_TEXT);
+ UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false);
BLF_disable(blf_mono_font, BLF_CLIPPING);
@@ -2547,7 +2543,7 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
immUnbindProgram();
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(fontid, TH_TEXT);
BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f);
BLF_draw(fontid, numstr, sizeof(numstr));
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 23b3af26f50..14d877a8d69 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -75,6 +75,18 @@ void fdrawbox(float x1, float y1, float x2, float y2)
glEnd();
}
+void fdrawbox_filled(float x1, float y1, float x2, float y2)
+{
+ glBegin(GL_POLYGON);
+
+ glVertex2f(x1, y1);
+ glVertex2f(x1, y2);
+ glVertex2f(x2, y2);
+ glVertex2f(x2, y1);
+
+ glEnd();
+}
+
void fdrawcheckerboard(float x1, float y1, float x2, float y2) /* DEPRECATED */
{
unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50};
@@ -323,6 +335,7 @@ static int get_cached_work_texture(int *r_w, int *r_h)
return texid;
}
+/* DEPRECATED: use immDrawPixelsTexScaled_clipping instead */
void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
int format, int type, int zoomfilter, void *rect,
float scaleX, float scaleY,
@@ -458,6 +471,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
+/* DEPRECATED: use immDrawPixelsTexScaled instead */
void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
int format, int type, int zoomfilter, void *rect,
float scaleX, float scaleY)
@@ -466,12 +480,14 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f);
}
+/* DEPRECATED: use immDrawPixelsTex instead */
void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
{
glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f);
}
+/* DEPRECATED: use immDrawPixelsTex_clipping instead */
void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h,
int format, int type, int zoomfilter, void *rect,
float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y)
@@ -585,6 +601,176 @@ void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int t
0.0f, 0.0f, 0.0f, 0.0f);
}
+/* TODO this is utterly slow and need some love
+ * but in the meantime it's not using deprecated api */
+void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
+ int format, int type, int zoomfilter, void *rect,
+ float scaleX, float scaleY,
+ float clip_min_x, float clip_min_y,
+ float clip_max_x, float clip_max_y,
+ float xzoom, float yzoom, float color[4])
+{
+ unsigned char *uc_rect = (unsigned char *) rect;
+ const float *f_rect = (float *)rect;
+ int subpart_x, subpart_y, tex_w, tex_h;
+ int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
+ int texid = get_cached_work_texture(&tex_w, &tex_h);
+ int components;
+ const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
+
+ /* Specify the color outside this function, and tex will modulate it.
+ * This is useful for changing alpha without using glPixelTransferf()
+ */
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ /* don't want nasty border artifacts */
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
+
+ /* setup seamless 2=on, 0=off */
+ seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
+
+ offset_x = tex_w - seamless;
+ offset_y = tex_h - seamless;
+
+ nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
+ nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
+
+ if (format == GL_RGBA)
+ components = 4;
+ else if (format == GL_RGB)
+ components = 3;
+ else if (format == GL_RED)
+ components = 1;
+ else {
+ BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
+ return;
+ }
+
+ if (type == GL_FLOAT) {
+ /* need to set internal format to higher range float */
+
+ /* NOTE: this could fail on some drivers, like mesa,
+ * but currently this code is only used by color
+ * management stuff which already checks on whether
+ * it's possible to use GL_RGBA16F_ARB
+ */
+
+ /* TODO viewport : remove extension */
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
+ }
+ else {
+ /* switch to 8bit RGBA for byte buffer */
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
+ }
+
+ VertexFormat *vert_format = immVertexFormat();
+ unsigned int pos = add_attrib(vert_format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int texco = add_attrib(vert_format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniform4fv("color", color);
+ immUniform1i("image", 0);
+
+ for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
+ for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
+ int remainder_x = img_w - subpart_x * offset_x;
+ int remainder_y = img_h - subpart_y * offset_y;
+ int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
+ int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
+ int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
+ int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
+ int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
+ int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
+ float rast_x = x + subpart_x * offset_x * xzoom;
+ float rast_y = y + subpart_y * offset_y * yzoom;
+ /* check if we already got these because we always get 2 more when doing seamless */
+ if (subpart_w <= seamless || subpart_h <= seamless)
+ continue;
+
+ if (use_clipping) {
+ if (rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX < clip_min_x ||
+ rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY < clip_min_y)
+ {
+ continue;
+ }
+ if (rast_x + (float)offset_left * xzoom > clip_max_x ||
+ rast_y + (float)offset_bot * yzoom > clip_max_y)
+ {
+ continue;
+ }
+ }
+
+ if (type == GL_FLOAT) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
+
+ /* add an extra border of pixels so linear looks ok at edges of full image */
+ if (subpart_w < tex_w)
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ if (subpart_h < tex_h)
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
+ if (subpart_w < tex_w && subpart_h < tex_h)
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
+
+ if (subpart_w < tex_w)
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ if (subpart_h < tex_h)
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
+ if (subpart_w < tex_w && subpart_h < tex_h)
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ }
+
+ immBegin(GL_TRIANGLE_FAN, 4);
+ immAttrib2f(texco, (float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
+ immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
+
+ immAttrib2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
+ immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);
+
+ immAttrib2f(texco, (float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
+ immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
+
+ immAttrib2f(texco, (float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
+ immVertex2f(pos, rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
+ immEnd();
+ }
+ }
+
+ immUnbindProgram();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+}
+
+void immDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
+ int format, int type, int zoomfilter, void *rect,
+ float scaleX, float scaleY, float xzoom, float yzoom, float color[4])
+{
+ immDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
+ scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color);
+}
+
+void immDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
+ float xzoom, float yzoom, float color[4])
+{
+ immDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color);
+}
+
+void immDrawPixelsTex_clipping(float x, float y, int img_w, int img_h,
+ int format, int type, int zoomfilter, void *rect,
+ float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
+ float xzoom, float yzoom, float color[4])
+{
+ immDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y, xzoom, yzoom, color);
+}
+
/* 2D Drawing Assistance */
void glaDefine2DArea(rcti *screen_rect)
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index c165bbfd301..c82a210725c 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -47,6 +47,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_gpencil.h"
+#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
@@ -60,20 +61,8 @@
#include "screen_intern.h"
-static unsigned int context_layers(bScreen *sc, Scene *scene, ScrArea *sa_ctx)
-{
- /* needed for 'USE_ALLSELECT' define, otherwise we end up editing off-screen layers. */
- if (sc && sa_ctx && (sa_ctx->spacetype == SPACE_BUTS)) {
- const unsigned int lay = BKE_screen_view3d_layer_all(sc);
- if (lay) {
- return lay;
- }
- }
- return scene->lay;
-}
-
const char *screen_context_dir[] = {
- "scene", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
+ "scene", "render_layer", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
"selected_objects", "selected_bases",
"editable_objects", "editable_bases",
"selected_editable_objects", "selected_editable_bases",
@@ -95,17 +84,9 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bScreen *sc = CTX_wm_screen(C);
ScrArea *sa = CTX_wm_area(C);
Scene *scene = sc->scene;
- Base *base;
-
-#if 0 /* Using the context breaks adding objects in the UI. Need to find out why - campbell */
- Object *obact = CTX_data_active_object(C);
- Object *obedit = CTX_data_edit_object(C);
- base = CTX_data_active_base(C);
-#else
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = scene->obedit;
- Object *obact = OBACT;
- base = BASACT;
-#endif
+ Object *obact = sl->basact ? sl->basact->object : NULL;
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, screen_context_dir);
@@ -115,84 +96,105 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
CTX_data_id_pointer_set(result, &scene->id);
return 1;
}
- else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
- const bool visible_objects = CTX_data_equals(member, "visible_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) {
- if (visible_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ else if (CTX_data_equals(member, "visible_objects")) {
+ Object *ob;
+ FOREACH_VISIBLE_OBJECT(sl, ob)
+ {
+ CTX_data_id_list_add(result, &ob->id);
+ }
+ FOREACH_VISIBLE_BASE_END
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selectable_objects")) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ CTX_data_id_list_add(result, &base->object->id);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
- else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
- const bool selectable_objects = CTX_data_equals(member, "selectable_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & lay) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
- if (selectable_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
+ else if (CTX_data_equals(member, "selected_objects")) {
+ Object *ob;
+ FOREACH_SELECTED_OBJECT(sl, ob)
+ {
+ CTX_data_id_list_add(result, &ob->id);
+ }
+ FOREACH_SELECTED_OBJECT_END
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_editable_objects")) {
+ Object *ob;
+ FOREACH_SELECTED_OBJECT(sl, ob)
+ {
+ if (0 == BKE_object_is_libdata(ob)) {
+ CTX_data_id_list_add(result, &ob->id);
}
}
+ FOREACH_SELECTED_OBJECT_END
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
- else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
- const bool selected_objects = CTX_data_equals(member, "selected_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
- if (selected_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ else if (CTX_data_equals(member, "editable_objects")) {
+ /* Visible + Editable, but not necessarily selected */
+ Object *ob;
+ FOREACH_VISIBLE_OBJECT(sl, ob)
+ {
+ if (0 == BKE_object_is_libdata(ob)) {
+ CTX_data_id_list_add(result, &ob->id);
}
}
+ FOREACH_VISIBLE_OBJECT_END
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
- else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
- const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (0 == BKE_object_is_libdata(base->object)) {
- if (selected_editable_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
+ else if ( CTX_data_equals(member, "visible_bases")) {
+ Base *base;
+ FOREACH_VISIBLE_BASE(sl, base)
+ {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ FOREACH_VISIBLE_BASE_END
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selectable_bases")) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) != 0) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_bases")) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ }
+ }
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ return 1;
+ }
+ else if (CTX_data_equals(member, "selected_editable_bases")) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ if (0 == BKE_object_is_libdata(base->object)) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
- else if (CTX_data_equals(member, "editable_objects") || CTX_data_equals(member, "editable_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
- const bool editable_objects = CTX_data_equals(member, "editable_objects");
-
+ else if (CTX_data_equals(member, "editable_bases")) {
/* Visible + Editable, but not necessarily selected */
- for (base = scene->base.first; base; base = base->next) {
- if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
if (0 == BKE_object_is_libdata(base->object)) {
- if (editable_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
}
}
@@ -344,8 +346,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
}
else if (CTX_data_equals(member, "active_base")) {
- if (base)
- CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, base);
+ if (sl->basact)
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact);
return 1;
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 32b63aca34c..a55d6c2143f 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -321,6 +321,10 @@ int ED_operator_info_active(bContext *C)
return ed_spacetype_test(C, SPACE_INFO);
}
+int ED_operator_collections_active(bContext *C)
+{
+ return ed_spacetype_test(C, SPACE_COLLECTIONS);
+}
int ED_operator_console_active(bContext *C)
{
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index feea9cf5b13..f2707b9399f 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -157,15 +157,12 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
- int filter;
View2D *v2d = &ar->v2d;
bDopeSheet *ads = &saction->ads;
AnimData *adt = NULL;
float act_start, act_end, y;
- size_t items;
- int height;
unsigned char col1[3], col2[3];
unsigned char col1a[3], col2a[3];
@@ -195,10 +192,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
/* build list of channels to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
+ int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
@@ -236,7 +233,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
case ANIMTYPE_SUMMARY:
{
/* reddish color from NLA */
- UI_ThemeColor4(TH_ANIM_ACTIVE);
+ immUniformThemeColor(TH_ANIM_ACTIVE);
break;
}
case ANIMTYPE_SCENE:
@@ -259,11 +256,11 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
bActionGroup *agrp = ale->data;
if (show_group_colors && agrp->customCol) {
if (sel) {
- unsigned char *cp = agrp->cs.select;
+ char *cp = agrp->cs.select;
immUniformColor4ub(cp[0], cp[1], cp[2], 0x45);
}
else {
- unsigned char *cp = agrp->cs.solid;
+ char *cp = agrp->cs.solid;
immUniformColor4ub(cp[0], cp[1], cp[2], 0x1D);
}
}
@@ -332,18 +329,29 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
y -= ACHANNEL_STEP(ac);
}
glDisable(GL_BLEND);
-
- /* Draw keyframes
+
+ /* black line marking 'current frame' for Time-Slide transform mode */
+ if (saction->flag & SACTION_MOVING) {
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
+ immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
+ immEnd();
+ }
+ immUnbindProgram();
+
+ /* Draw keyframes
* 1) Only channels that are visible in the Action Editor get drawn/evaluated.
* This is to try to optimize this for heavier data sets
* 2) Keyframes which are out of view horizontally are disregarded
*/
y = (float)(-ACHANNEL_HEIGHT(ac));
-
+
for (ale = anim_data.first; ale; ale = ale->next) {
const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
-
+
/* check if visible */
if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
@@ -351,7 +359,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* check if anything to show for this channel */
if (ale->datatype != ALE_NONE) {
adt = ANIM_nla_mapping_get(ac, ale);
-
+
/* draw 'keyframes' for each specific datatype */
switch (ale->datatype) {
case ALE_ALL:
@@ -381,21 +389,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
}
}
-
+
y -= ACHANNEL_STEP(ac);
}
-
- /* free tempolary channels used for drawing */
- ANIM_animdata_freelist(&anim_data);
- /* black line marking 'current frame' for Time-Slide transform mode */
- if (saction->flag & SACTION_MOVING) {
- immUniformColor3f(0.0f, 0.0f, 0.0f);
-
- immBegin(GL_LINES, 2);
- immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
- immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
- immEnd();
- }
- immUnbindProgram();
+ /* free temporary channels used for drawing */
+ ANIM_animdata_freelist(&anim_data);
}
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 5ff1d758563..8c278c0b3ae 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -96,6 +96,7 @@ void ED_spacetypes_init(void)
ED_spacetype_console();
ED_spacetype_userpref();
ED_spacetype_clip();
+ ED_spacetype_collections();
// ...
/* register operator types for screen and all spaces */
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index da3364d872d..f53d98a1b59 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -49,6 +49,7 @@
#include "BKE_context.h"
#include "BKE_action.h"
+#include "BKE_layer.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_paint.h"
@@ -180,7 +181,9 @@ static int buttons_context_path_object(ButsContextPath *path)
/* if we have a scene, use the scene's active object */
else if (buttons_context_path_scene(path)) {
scene = path->ptr[path->len - 1].data;
- ob = (scene->basact) ? scene->basact->object : NULL;
+ TODO_LAYER_CONTEXT; /* use context, not active one */
+ SceneLayer *sl = BKE_scene_layer_active(scene);
+ ob = (sl->basact) ? sl->basact->object : NULL;
if (ob) {
RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
@@ -553,6 +556,28 @@ static bool buttons_context_linestyle_pinnable(const bContext *C)
}
#endif
+static int buttons_context_path_collection(const bContext *C, ButsContextPath *path)
+{
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* if we already have a (pinned) Collection, we're done */
+ if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) {
+ return 1;
+ }
+
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ LayerCollection *sc = BKE_layer_collection_active(sl);
+
+ if (sc) {
+ RNA_pointer_create(NULL, &RNA_LayerCollection, sc, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+
+ /* no path to a collection possible */
+ return 0;
+}
+
static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
{
SpaceButs *sbuts = CTX_wm_space_buts(C);
@@ -627,7 +652,10 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_BONE_CONSTRAINT:
found = buttons_context_path_pose_bone(path);
break;
- default:
+ case BCONTEXT_COLLECTION:
+ found = buttons_context_path_collection(C, path);
+ break;
+ default:
found = 0;
break;
}
@@ -744,7 +772,7 @@ const char *buttons_context_dir[] = {
"texture", "texture_user", "texture_user_property", "bone", "edit_bone",
"pose_bone", "particle_system", "particle_system_editable", "particle_settings",
"cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint",
- "line_style", NULL
+ "line_style", "collection", NULL
};
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
@@ -1064,6 +1092,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_FreestyleLineStyle);
return 1;
}
+ else if (CTX_data_equals(member, "collection")) {
+ set_pointer_type(path, result, &RNA_LayerCollection);
+ return 1;
+ }
else {
return 0; /* not found */
}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index e4c23ad74f8..608287939bd 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -171,6 +171,8 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, "constraint", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_BONE_CONSTRAINT)
ED_region_panels(C, ar, "bone_constraint", sbuts->mainb, vertical);
+ else if (sbuts->mainb == BCONTEXT_COLLECTION)
+ ED_region_panels(C, ar, "collection", sbuts->mainb, vertical);
sbuts->re_align = 0;
sbuts->mainbo = sbuts->mainb;
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 4bf4c1e7baa..872e62dbc97 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -42,8 +42,6 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "BIF_gl.h"
-
#include "WM_types.h"
#include "UI_interface.h"
@@ -54,6 +52,9 @@
#include "RNA_access.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+
#include "clip_intern.h" /* own include */
static void track_channel_color(MovieTrackingTrack *track, float default_color[3], float color[3])
@@ -72,78 +73,25 @@ static void track_channel_color(MovieTrackingTrack *track, float default_color[3
}
}
-static void draw_keyframe_shape(float x, float y, float xscale, float yscale, bool sel, float alpha)
+static void draw_keyframe_shape(float x, float y, bool sel, float alpha,
+ unsigned int pos_id, unsigned int color_id)
{
- /* coordinates for diamond shape */
- static const float _unit_diamond_shape[4][2] = {
- {0.0f, 1.0f}, /* top vert */
- {1.0f, 0.0f}, /* mid-right */
- {0.0f, -1.0f}, /* bottom vert */
- {-1.0f, 0.0f} /* mid-left */
- };
- static GLuint displist1 = 0;
- static GLuint displist2 = 0;
- int hsize = STRIP_HEIGHT_HALF;
-
- /* initialize 2 display lists for diamond shape - one empty, one filled */
- if (displist1 == 0) {
- displist1 = glGenLists(1);
- glNewList(displist1, GL_COMPILE);
-
- glBegin(GL_LINE_LOOP);
- glVertex2fv(_unit_diamond_shape[0]);
- glVertex2fv(_unit_diamond_shape[1]);
- glVertex2fv(_unit_diamond_shape[2]);
- glVertex2fv(_unit_diamond_shape[3]);
- glEnd();
- glEndList();
+ float color[4] = { 0.91f, 0.91f, 0.91f, alpha };
+ if (sel) {
+ UI_GetThemeColorShadeAlpha4fv(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha), color);
}
- if (displist2 == 0) {
- displist2 = glGenLists(1);
- glNewList(displist2, GL_COMPILE);
-
- glBegin(GL_QUADS);
- glVertex2fv(_unit_diamond_shape[0]);
- glVertex2fv(_unit_diamond_shape[1]);
- glVertex2fv(_unit_diamond_shape[2]);
- glVertex2fv(_unit_diamond_shape[3]);
- glEnd();
- glEndList();
- }
-
- glPushMatrix();
-
- /* adjust view transform before starting */
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
-
- /* anti-aliased lines for more consistent appearance */
- glEnable(GL_LINE_SMOOTH);
-
- if (sel)
- UI_ThemeColorShadeAlpha(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha));
- else
- glColor4f(0.91f, 0.91f, 0.91f, alpha);
-
- glCallList(displist2);
- /* exterior - black frame */
- glColor4f(0.0f, 0.0f, 0.0f, alpha);
- glCallList(displist1);
-
- glDisable(GL_LINE_SMOOTH);
-
- /* restore view transform */
- glPopMatrix();
+ immAttrib4fv(color_id, color);
+ immVertex2f(pos_id, x, y);
}
-static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip)
+static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigned int pos_id)
{
View2D *v2d = &ar->v2d;
MovieTracking *tracking = &clip->tracking;
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
MovieTrackingDopesheetCoverageSegment *coverage_segment;
-
+
for (coverage_segment = dopesheet->coverage_segments.first;
coverage_segment;
coverage_segment = coverage_segment->next)
@@ -153,12 +101,13 @@ static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip)
int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame);
if (coverage_segment->coverage == TRACKING_COVERAGE_BAD) {
- glColor4f(1.0f, 0.0f, 0.0f, 0.07f);
+ immUniformColor4f(1.0f, 0.0f, 0.0f, 0.07f);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 0.0f, 0.07f);
}
- else
- glColor4f(1.0f, 1.0f, 0.0f, 0.07f);
- glRectf(start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax);
+ immRectf(pos_id, start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax);
}
}
}
@@ -175,18 +124,21 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
MovieTracking *tracking = &clip->tracking;
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
MovieTrackingDopesheetChannel *channel;
- float y, xscale, yscale;
float strip[4], selected_strip[4];
float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
+ unsigned int keyframe_ct = 0;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
v2d->tot.ymin = (float)(-height);
- y = (float) CHANNEL_FIRST;
-
- UI_view2d_scale_get(v2d, &xscale, &yscale);
+ float y = (float) CHANNEL_FIRST;
/* setup colors for regular and selected strips */
UI_GetThemeColor3fv(TH_STRIP, strip);
@@ -197,7 +149,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
glEnable(GL_BLEND);
- clip_draw_dopesheet_background(ar, clip);
+ clip_draw_dopesheet_background(ar, clip, pos_id);
for (channel = dopesheet->channels.first; channel; channel = channel->next) {
float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
@@ -208,7 +160,6 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
{
MovieTrackingTrack *track = channel->track;
- float alpha;
int i;
bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
@@ -218,32 +169,26 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f};
track_channel_color(track, default_color, color);
- glColor4fv(color);
+ immUniformColor4fv(color);
- glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
- v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
+ immRectf(pos_id, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
+ v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
}
- alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;
-
/* tracked segments */
for (i = 0; i < channel->tot_segment; i++) {
int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);
- if (sel)
- glColor4fv(selected_strip);
- else
- glColor4fv(strip);
+ immUniformColor4fv(sel ? selected_strip : strip);
if (start_frame != end_frame) {
- glRectf(start_frame, (float) y - STRIP_HEIGHT_HALF,
- end_frame, (float) y + STRIP_HEIGHT_HALF);
- draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
- draw_keyframe_shape(end_frame, y, xscale, yscale, sel, alpha);
+ immRectf(pos_id, start_frame, (float) y - STRIP_HEIGHT_HALF,
+ end_frame, (float) y + STRIP_HEIGHT_HALF);
+ keyframe_ct += 2;
}
else {
- draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
+ keyframe_ct++;
}
}
@@ -253,9 +198,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
MovieTrackingMarker *marker = &track->markers[i];
if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
- int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
-
- draw_keyframe_shape(framenr, y, xscale, yscale, sel, alpha);
+ keyframe_ct++;
}
i++;
@@ -266,6 +209,76 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
y -= CHANNEL_STEP;
}
+ immUnbindProgram();
+
+ if (keyframe_ct > 0) {
+ /* draw keyframe markers */
+ format = immVertexFormat();
+ pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT);
+ unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+ unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(PRIM_POINTS, keyframe_ct);
+
+ /* all same size with black outline */
+ immAttrib1f(size_id, 2.0f * STRIP_HEIGHT_HALF);
+ immAttrib3ub(outline_color_id, 0, 0, 0);
+
+ y = (float) CHANNEL_FIRST; /* start again at the top */
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
+ float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
+ {
+ MovieTrackingTrack *track = channel->track;
+ int i;
+ bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
+ float alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;
+
+ /* tracked segments */
+ for (i = 0; i < channel->tot_segment; i++) {
+ int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
+ int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);
+
+ if (start_frame != end_frame) {
+ draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
+ draw_keyframe_shape(end_frame, y, sel, alpha, pos_id, color_id);
+ }
+ else {
+ draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
+ }
+ }
+
+ /* keyframes */
+ i = 0;
+ while (i < track->markersnr) {
+ MovieTrackingMarker *marker = &track->markers[i];
+
+ if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
+ int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
+
+ draw_keyframe_shape(framenr, y, sel, alpha, pos_id, color_id);
+ }
+
+ i++;
+ }
+ }
+
+ /* adjust y-position for next one */
+ y -= CHANNEL_STEP;
+ }
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+ }
+
glDisable(GL_BLEND);
}
@@ -279,22 +292,15 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
SpaceClip *sc = CTX_wm_space_clip(C);
View2D *v2d = &ar->v2d;
MovieClip *clip = ED_space_clip_get_clip(sc);
- MovieTracking *tracking;
- MovieTrackingDopesheet *dopesheet;
- MovieTrackingDopesheetChannel *channel;
uiStyle *style = UI_style_get();
- uiBlock *block;
int fontid = style->widget.uifont_id;
- int height;
- float y;
- PropertyRNA *chan_prop_lock;
-
+
if (!clip)
return;
- tracking = &clip->tracking;
- dopesheet = &tracking->dopesheet;
- height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
if (height > BLI_rcti_size_y(&v2d->mask)) {
/* don't use totrect set, as the width stays the same
@@ -309,6 +315,37 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
/* loop through channels, and set up drawing depending on their type
* first pass: just the standard GL-drawing for backdrop + text
*/
+ float y = (float) CHANNEL_FIRST;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ MovieTrackingDopesheetChannel *channel;
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
+ float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
+
+ /* check if visible */
+ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
+ {
+ MovieTrackingTrack *track = channel->track;
+ float color[3];
+ track_channel_color(track, NULL, color);
+ immUniformColor3fv(color);
+
+ immRectf(pos, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
+ v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
+ }
+
+ /* adjust y-position for next one */
+ y -= CHANNEL_STEP;
+ }
+ immUnbindProgram();
+
+ /* second pass: text */
y = (float) CHANNEL_FIRST;
BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
@@ -322,21 +359,11 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
{
MovieTrackingTrack *track = channel->track;
- float font_height, color[3];
bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
- track_channel_color(track, NULL, color);
- glColor3fv(color);
-
- glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
- v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
-
- if (sel)
- UI_ThemeColor(TH_TEXT_HI);
- else
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT);
- font_height = BLF_height(fontid, channel->name, sizeof(channel->name));
+ float font_height = BLF_height(fontid, channel->name, sizeof(channel->name));
BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD,
y - font_height / 2.0f, 0.0f);
BLF_draw(fontid, channel->name, strlen(channel->name));
@@ -346,12 +373,12 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
y -= CHANNEL_STEP;
}
- /* second pass: widgets */
- block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ /* third pass: widgets */
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
y = (float) CHANNEL_FIRST;
/* get RNA properties (once) */
- chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock");
+ PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock");
BLI_assert(chan_prop_lock);
glEnable(GL_BLEND);
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 424d25defdd..b373358b49c 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -42,7 +42,10 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_types.h"
@@ -53,52 +56,30 @@
#include "clip_intern.h" // own include
-static void draw_curve_knot(float x, float y, float xscale, float yscale, float hsize)
-{
- 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();
- }
-
- glPushMatrix();
-
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
- glCallList(displist);
-
- glPopMatrix();
-}
+typedef struct TrackMotionCurveUserData {
+ MovieTrackingTrack *act_track;
+ bool sel;
+ float xscale, yscale, hsize;
+ unsigned int pos;
+} TrackMotionCurveUserData;
-static void tracking_segment_point_cb(void *UNUSED(userdata), MovieTrackingTrack *UNUSED(track),
+static void tracking_segment_point_cb(void *userdata, MovieTrackingTrack *UNUSED(track),
MovieTrackingMarker *UNUSED(marker), int UNUSED(coord),
int scene_framenr, float val)
{
- glVertex2f(scene_framenr, val);
+ TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata;
+
+ immVertex2f(data->pos, scene_framenr, val);
}
static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord)
{
- const float colors[2][3] = {
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f},
- };
- float col[4];
+ TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata;
+ float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- copy_v3_v3(col, colors[coord]);
+ col[coord] = 1.0f;
- if (track == userdata) {
+ if (track == data->act_track) {
col[3] = 1.0f;
glLineWidth(2.0f);
}
@@ -107,22 +88,17 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track,
glLineWidth(1.0f);
}
- glColor4fv(col);
+ immUniformColor4fv(col);
- glBegin(GL_LINE_STRIP);
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GL_LINE_STRIP, track->markersnr);
}
static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord))
{
- glEnd();
+ immEnd();
}
-typedef struct TrackMotionCurveUserData {
- MovieTrackingTrack *act_track;
- bool sel;
- float xscale, yscale, hsize;
-} TrackMotionCurveUserData;
-
static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track,
MovieTrackingMarker *marker, int coord, int scene_framenr, float val)
{
@@ -136,16 +112,20 @@ static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track,
sel = (marker->flag & sel_flag) ? 1 : 0;
if (sel == data->sel) {
- if (sel)
- UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
- else
- UI_ThemeColor(TH_HANDLE_VERTEX);
+ immUniformThemeColor(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX);
+
+ glPushMatrix();
+ glTranslatef(scene_framenr, val, 0.0f);
+ glScalef(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize, 1.0f);
+ gpuMatrixUpdate_legacy();
+
+ imm_draw_lined_circle(data->pos, 0, 0, 0.7, 8);
- draw_curve_knot(scene_framenr, val, data->xscale, data->yscale, data->hsize);
+ glPopMatrix();
}
}
-static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc)
+static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int pos)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -162,18 +142,21 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc)
userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
userdata.sel = false;
userdata.act_track = act_track;
+ userdata.pos = pos;
UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale);
clip_graph_tracking_values_iterate(sc,
(sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
(sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
&userdata, tracking_segment_knot_cb, NULL, NULL);
+ gpuMatrixUpdate_legacy();
+
/* draw graph lines */
glEnable(GL_BLEND);
clip_graph_tracking_values_iterate(sc,
(sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
(sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
- act_track, tracking_segment_point_cb, tracking_segment_start_cb,
+ &userdata, tracking_segment_point_cb, tracking_segment_start_cb,
tracking_segment_end_cb);
glDisable(GL_BLEND);
@@ -183,6 +166,8 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc)
(sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
(sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
&userdata, tracking_segment_knot_cb, NULL, NULL);
+
+ gpuMatrixUpdate_legacy();
}
typedef struct TrackErrorCurveUserData {
@@ -195,6 +180,7 @@ typedef struct TrackErrorCurveUserData {
float projection_matrix[4][4];
int width, height;
float aspy;
+ unsigned int pos;
} TrackErrorCurveUserData;
static void tracking_error_segment_point_cb(void *userdata,
@@ -230,7 +216,7 @@ static void tracking_error_segment_point_cb(void *userdata,
sub_v2_v2v2(delta, reprojected_position, marker_position);
reprojection_error = len_v2(delta) * weight;
- glVertex2f(scene_framenr, reprojection_error);
+ immVertex2f(data->pos, scene_framenr, reprojection_error);
}
}
@@ -249,20 +235,21 @@ static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *
glLineWidth(1.0f);
}
- glColor4fv(col);
+ immUniformColor4fv(col);
- glBegin(GL_LINE_STRIP);
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GL_LINE_STRIP, track->markersnr);
}
}
static void tracking_error_segment_end_cb(void *UNUSED(userdata), int coord)
{
if (coord == 1) {
- glEnd();
+ immEnd();
}
}
-static void draw_tracks_error_curves(SpaceClip *sc)
+static void draw_tracks_error_curves(SpaceClip *sc, unsigned int pos)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -273,6 +260,7 @@ static void draw_tracks_error_curves(SpaceClip *sc)
data.tracking_object = BKE_tracking_object_get_active(tracking);
data.active_track = BKE_tracking_track_get_active(tracking);
data.matrix_initialized = false;
+ data.pos = pos;
BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height);
data.aspy = 1.0f / tracking->camera.pixel_aspect;
@@ -289,37 +277,38 @@ static void draw_tracks_error_curves(SpaceClip *sc)
tracking_error_segment_end_cb);
}
-static void draw_frame_curves(SpaceClip *sc)
+static void draw_frame_curves(SpaceClip *sc, unsigned int pos)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
int i, lines = 0, prevfra = 0;
- glColor3f(0.0f, 0.0f, 1.0f);
+ immUniformColor3f(0.0f, 0.0f, 1.0f);
for (i = 0; i < reconstruction->camnr; i++) {
MovieReconstructedCamera *camera = &reconstruction->cameras[i];
int framenr;
if (lines && camera->framenr != prevfra + 1) {
- glEnd();
+ immEnd();
lines = 0;
}
if (!lines) {
- glBegin(GL_LINE_STRIP);
+ immBeginAtMost(GL_LINE_STRIP, reconstruction->camnr);
lines = 1;
}
framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr);
- glVertex2f(framenr, camera->error);
+ immVertex2f(pos, framenr, camera->error);
prevfra = camera->framenr;
}
- if (lines)
- glEnd();
+ if (lines) {
+ immEnd();
+ }
}
void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
@@ -334,17 +323,26 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
UI_view2d_grid_free(grid);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (clip) {
- if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION)
- draw_tracks_motion_curves(v2d, sc);
+ if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) {
+ draw_tracks_motion_curves(v2d, sc, pos);
+ }
- if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR)
- draw_tracks_error_curves(sc);
+ if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) {
+ draw_tracks_error_curves(sc, pos);
+ }
- if (sc->flag & SC_SHOW_GRAPH_FRAMES)
- draw_frame_curves(sc);
+ if (sc->flag & SC_SHOW_GRAPH_FRAMES) {
+ draw_frame_curves(sc, pos);
+ }
}
+ immUnbindProgram();
+
/* frame range */
clip_draw_sfra_efra(v2d, scene);
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 547c2fba66f..6026036c05d 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -43,8 +43,7 @@
#include "BKE_tracking.h"
#include "BKE_depsgraph.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_immediate.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -52,7 +51,6 @@
#include "ED_screen.h"
#include "ED_clip.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -237,31 +235,35 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y)
void clip_draw_cfra(SpaceClip *sc, ARegion *ar, Scene *scene)
{
+ /* Draw a light green line to indicate current frame */
View2D *v2d = &ar->v2d;
- float xscale, yscale;
+ float x = (float)(sc->user.framenr * scene->r.framelen);
- /* Draw a light green line to indicate current frame */
- UI_ThemeColor(TH_CFRAME);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
- float x = (float)(sc->user.framenr * scene->r.framelen);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CFRAME);
+ glLineWidth(2.0f);
- glLineWidth(2.0);
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, x, v2d->cur.ymin);
+ immVertex2f(pos, x, v2d->cur.ymax);
+ immEnd();
- glBegin(GL_LINES);
- glVertex2f(x, v2d->cur.ymin);
- glVertex2f(x, v2d->cur.ymax);
- glEnd();
+ immUnbindProgram();
UI_view2d_view_orthoSpecial(ar, v2d, 1);
/* because the frame number text is subject to the same scaling as the contents of the view */
+ float xscale, yscale;
UI_view2d_scale_get(v2d, &xscale, &yscale);
+ glPushMatrix();
glScalef(1.0f / xscale, 1.0f, 1.0f);
ED_region_cache_draw_curfra_label(sc->user.framenr, (float)sc->user.framenr * xscale, 18);
/* restore view transform */
- glScalef(xscale, 1.0, 1.0);
+ glPopMatrix();
}
void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
@@ -271,15 +273,27 @@ void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
/* currently clip editor supposes that editing clip length is equal to scene frame range */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax);
- glRectf((float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax);
+ immRectf(pos, (float)EFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+
glDisable(GL_BLEND);
- UI_ThemeColorShade(TH_BACK, -60);
+ immUniformThemeColorShade(TH_BACK, -60);
/* thin lines where the actual frames are */
- fdrawline((float)SFRA, v2d->cur.ymin, (float)SFRA, v2d->cur.ymax);
- fdrawline((float)EFRA, v2d->cur.ymin, (float)EFRA, v2d->cur.ymax);
+ glLineWidth(1.0f);
+
+ immBegin(GL_LINES, 4);
+ immVertex2f(pos, (float)SFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)SFRA, v2d->cur.ymax);
+ immVertex2f(pos, (float)EFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)EFRA, v2d->cur.ymax);
+ immEnd();
+
+ immUnbindProgram();
}
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index f81180d65a9..12b97504dc7 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -44,6 +44,7 @@
#include "BKE_tracking.h"
#include "BKE_global.h"
#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -69,17 +70,17 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
return camera;
}
- for (Base *base = scene->base.first;
- base != NULL;
- base = base->next)
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
{
- if (base->object->type == OB_CAMERA) {
- if (BKE_object_movieclip_get(scene, base->object, false) == clip) {
- camera = base->object;
+ if (ob->type == OB_CAMERA) {
+ if (BKE_object_movieclip_get(scene, ob, false) == clip) {
+ camera = ob;
break;
}
}
}
+ FOREACH_SCENE_OBJECT_END
return camera;
}
@@ -87,6 +88,7 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
static Object *get_orientation_object(bContext *C)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
@@ -97,7 +99,7 @@ static Object *get_orientation_object(bContext *C)
object = get_camera_with_movieclip(scene, clip);
}
else {
- object = OBACT;
+ object = OBACT_NEW;
}
if (object != NULL && object->parent != NULL) {
@@ -111,7 +113,7 @@ static int set_orientation_poll(bContext *C)
{
SpaceClip *sc = CTX_wm_space_clip(C);
if (sc != NULL) {
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
if (clip != NULL) {
MovieTracking *tracking = &clip->tracking;
@@ -120,7 +122,7 @@ static int set_orientation_poll(bContext *C)
return true;
}
else {
- return OBACT != NULL;
+ return OBACT_NEW != NULL;
}
}
}
diff --git a/source/blender/editors/space_collections/CMakeLists.txt b/source/blender/editors/space_collections/CMakeLists.txt
new file mode 100644
index 00000000000..1cc4a40d657
--- /dev/null
+++ b/source/blender/editors/space_collections/CMakeLists.txt
@@ -0,0 +1,45 @@
+# ***** 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): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ collections_ops.c
+ space_collections.c
+
+ collections_intern.h
+)
+
+blender_add_lib(bf_editor_space_collections "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_collections/collections_intern.h b/source/blender/editors/space_collections/collections_intern.h
new file mode 100644
index 00000000000..866f59659c3
--- /dev/null
+++ b/source/blender/editors/space_collections/collections_intern.h
@@ -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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_collections/collections_intern.h
+ * \ingroup spcollections
+ */
+
+#ifndef __COLLECTIONS_INTERN_H__
+#define __COLLECTIONS_INTERN_H__
+
+struct wmKeyConfig;
+
+/* collections_ops.c */
+void collections_operatortypes(void);
+void collections_keymap(struct wmKeyConfig *keyconf);
+
+#endif /* __COLLECTIONS_INTERN_H__ */
+
diff --git a/source/blender/editors/space_collections/collections_ops.c b/source/blender/editors/space_collections/collections_ops.c
new file mode 100644
index 00000000000..7e1bf8091b0
--- /dev/null
+++ b/source/blender/editors/space_collections/collections_ops.c
@@ -0,0 +1,340 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_collections/collections_ops.c
+ * \ingroup spcollections
+ */
+
+#include "BKE_context.h"
+#include "BKE_layer.h"
+#include "BKE_report.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "collections_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/* polls */
+
+static SceneCollection *collection_manager_collection_active(bContext *C)
+{
+ TODO_LAYER_OPERATORS;
+ /* consider that we may have overrides active
+ * leading to no active collections */
+ return CTX_data_scene_collection(C);
+}
+
+static int operator_not_master_collection_active(bContext *C)
+{
+ SceneCollection *sc = collection_manager_collection_active(C);
+ if (sc == NULL) {
+ return 1;
+ }
+
+ return (sc == BKE_collection_master(CTX_data_scene(C))) ? 0 : 1;
+}
+
+static int operator_top_collection_active(bContext *C)
+{
+ SceneCollection *sc = collection_manager_collection_active(C);
+ if (sc == NULL) {
+ return 0;
+ }
+
+ TODO_LAYER_OPERATORS;
+ /* see if it's a top collection */
+ return 1;
+}
+
+static int operator_collection_active(bContext *C)
+{
+ return collection_manager_collection_active(C) ? 1 : 0;
+}
+
+/* -------------------------------------------------------------------- */
+/* collection manager operators */
+
+static int collection_link_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_link not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+static void COLLECTIONS_OT_collection_link(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Collection";
+ ot->idname = "COLLECTIONS_OT_collection_link";
+ ot->description = "Link a new collection to the active layer";
+
+ /* api callbacks */
+ ot->invoke = collection_link_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int collection_unlink_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_unlink not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+static void COLLECTIONS_OT_collection_unlink(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Collection";
+ ot->idname = "COLLECTIONS_OT_collection_unlink";
+ ot->description = "Link a new collection to the active layer";
+
+ /* api callbacks */
+ ot->invoke = collection_unlink_invoke;
+ ot->poll = operator_top_collection_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+
+ SceneCollection *sc = BKE_collection_add(scene, NULL, NULL);
+ BKE_collection_link(sl, sc);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+static void COLLECTIONS_OT_collection_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Collection";
+ ot->idname = "COLLECTIONS_OT_collection_new";
+ ot->description = "Add a new collection to the scene, and link it to the active layer";
+
+ /* api callbacks */
+ ot->exec = collection_new_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ TODO_LAYER_OVERRIDE;
+ BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_override_new not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+static void COLLECTIONS_OT_override_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Override";
+ ot->idname = "COLLECTIONS_OT_override_new";
+ ot->description = "Add a new override to the active collection";
+
+ /* api callbacks */
+ ot->invoke = override_new_invoke;
+ ot->poll = operator_collection_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int delete_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_delete not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+static void COLLECTIONS_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete";
+ ot->idname = "COLLECTIONS_OT_delete";
+ ot->description = "Delete active override or collection";
+
+ /* api callbacks */
+ ot->invoke = delete_invoke;
+ ot->poll = operator_not_master_collection_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int select_exec(bContext *C, wmOperator *op)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ const int collection_index = RNA_int_get(op->ptr, "collection_index");
+ sl->active_collection = collection_index;
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+static void COLLECTIONS_OT_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select";
+ ot->idname = "COLLECTIONS_OT_select";
+ ot->description = "Change active collection or override";
+
+ /* api callbacks */
+ ot->exec = select_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index",
+ "Index of collection to select", 0, INT_MAX);
+}
+
+static int rename_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_rename not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+static void COLLECTIONS_OT_rename(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Rename";
+ ot->idname = "COLLECTIONS_OT_rename";
+ ot->description = "Rename active collection or override";
+
+ /* api callbacks */
+ ot->invoke = rename_invoke;
+ ot->poll = operator_not_master_collection_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* -------------------------------------------------------------------- */
+/* property editor operators */
+
+static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+static void COLLECTIONS_OT_objects_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Objects";
+ ot->idname = "COLLECTIONS_OT_objects_add";
+ ot->description = "Add selected objects to collection";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void COLLECTIONS_OT_objects_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Object";
+ ot->idname = "COLLECTIONS_OT_objects_remove";
+ ot->description = "Remove object from collection";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void COLLECTIONS_OT_objects_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Objects";
+ ot->idname = "COLLECTIONS_OT_objects_select";
+ ot->description = "Selected collection objects";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void COLLECTIONS_OT_objects_deselect(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Deselect Objects";
+ ot->idname = "COLLECTIONS_OT_objects_deselect";
+ ot->description = "Deselected collection objects";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ************************** registration - operator types **********************************/
+
+void collections_operatortypes(void)
+{
+ WM_operatortype_append(COLLECTIONS_OT_delete);
+ WM_operatortype_append(COLLECTIONS_OT_select);
+ WM_operatortype_append(COLLECTIONS_OT_rename);
+ WM_operatortype_append(COLLECTIONS_OT_collection_link);
+ WM_operatortype_append(COLLECTIONS_OT_collection_unlink);
+ WM_operatortype_append(COLLECTIONS_OT_collection_new);
+ WM_operatortype_append(COLLECTIONS_OT_override_new);
+
+ WM_operatortype_append(COLLECTIONS_OT_objects_add);
+ WM_operatortype_append(COLLECTIONS_OT_objects_remove);
+ WM_operatortype_append(COLLECTIONS_OT_objects_select);
+ WM_operatortype_append(COLLECTIONS_OT_objects_deselect);
+}
+
+void collections_keymap(wmKeyConfig *keyconf)
+{
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Collections Manager", SPACE_COLLECTIONS, 0);
+
+ /* selection */
+ WM_keymap_add_item(keymap, "COLLECTIONS_OT_select", LEFTMOUSE, KM_CLICK, 0, 0);
+
+ WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
+ WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "COLLECTIONS_OT_collection_new", NKEY, KM_PRESS, KM_CTRL, 0);
+
+ WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", DELKEY, KM_PRESS, 0, 0);
+}
diff --git a/source/blender/editors/space_collections/space_collections.c b/source/blender/editors/space_collections/space_collections.c
new file mode 100644
index 00000000000..7dd50e5cbac
--- /dev/null
+++ b/source/blender/editors/space_collections/space_collections.c
@@ -0,0 +1,182 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_collections/space_collections.c
+ * \ingroup spcollections
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BIF_gl.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "collections_intern.h" /* own include */
+
+/* ******************** default callbacks for collection manager space ***************** */
+
+static SpaceLink *collections_new(const bContext *UNUSED(C))
+{
+ ARegion *ar;
+ SpaceCollections *scollection; /* hmm, that's actually a good band name... */
+
+ scollection = MEM_callocN(sizeof(SpaceCollections), __func__);
+ scollection->spacetype = SPACE_COLLECTIONS;
+
+ /* header */
+ ar = MEM_callocN(sizeof(ARegion), "header for collection manager");
+ BLI_addtail(&scollection->regionbase, ar);
+ ar->regiontype = RGN_TYPE_HEADER;
+ ar->alignment = RGN_ALIGN_BOTTOM;
+
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for collection manager");
+ BLI_addtail(&scollection->regionbase, ar);
+ ar->regiontype = RGN_TYPE_WINDOW;
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
+ ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+
+ return (SpaceLink *)scollection;
+}
+
+static void collections_free(SpaceLink *UNUSED(sl))
+{
+}
+
+static SpaceLink *collections_duplicate(SpaceLink *sl)
+{
+ SpaceCollections *scollection = MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ return (SpaceLink *)scollection;
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void collection_main_region_init(wmWindowManager *wm, ARegion *ar)
+{
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+ ar->v2d.scroll |= (V2D_SCROLL_VERTICAL_FULLR | V2D_SCROLL_HORIZONTAL_FULLR);
+
+ /* own keymap */
+ wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Layer Manager", SPACE_COLLECTIONS, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void collections_main_region_draw(const bContext *C, ARegion *ar)
+{
+ SpaceCollections *spc = CTX_wm_space_collections(C);
+ View2D *v2d = &ar->v2d;
+
+ if (spc->flag & SC_COLLECTION_DATA_REFRESH) {
+ }
+
+ /* v2d has initialized flag, so this call will only set the mask correct */
+ UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
+
+ UI_ThemeClearColor(TH_BACK);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* reset view matrix */
+ UI_view2d_view_restore(C);
+
+ /* scrollers */
+ View2DScrollers *scrollers;
+ scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+}
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void collections_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+{
+ ED_region_header_init(ar);
+}
+
+static void collections_header_region_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_header(C, ar);
+}
+
+static void collections_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+{
+ switch (wmn->category) {
+ case NC_SCENE:
+ if (wmn->data == ND_LAYER) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_COLLECTIONS) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_collections(void)
+{
+ SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype collections");
+ ARegionType *art;
+
+ st->spaceid = SPACE_COLLECTIONS;
+ strncpy(st->name, "LayerManager", BKE_ST_MAXNAME);
+
+ st->new = collections_new;
+ st->free = collections_free;
+ st->duplicate = collections_duplicate;
+ st->operatortypes = collections_operatortypes;
+ st->keymap = collections_keymap;
+
+ /* regions: main window */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype collections region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init = collection_main_region_init;
+ art->draw = collections_main_region_draw;
+ art->listener = collections_main_region_listener;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: header */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype collections header");
+ art->regionid = RGN_TYPE_HEADER;
+ art->prefsizey = HEADERY;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
+ art->init = collections_header_region_init;
+ art->draw = collections_header_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ BKE_spacetype_register(st);
+}
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index f049d616aa7..06066372828 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -290,7 +290,8 @@ static void file_draw_icon(uiBlock *block, const char *path, int sx, int sy, int
}
-static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align)
+static void file_draw_string(int sx, int sy, const char *string, float width, int height, short align,
+ const unsigned char col[4])
{
uiStyle *style;
uiFontStyle fs;
@@ -315,7 +316,7 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in
rect.ymin = sy - height;
rect.ymax = sy;
- UI_fontstyle_draw(&fs, &rect, fname);
+ UI_fontstyle_draw(&fs, &rect, fname, col);
}
void file_calc_previews(const bContext *C, ARegion *ar)
@@ -537,6 +538,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
short align;
bool do_drag;
int column_space = 0.6f * UI_UNIT_X;
+ unsigned char text_col[4];
const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size));
@@ -645,7 +647,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
}
- UI_ThemeColor4(TH_TEXT);
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
if (file_selflag & FILE_SEL_EDITING) {
uiBut *but;
@@ -676,7 +678,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
if (!(file_selflag& FILE_SEL_EDITING)) {
int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy;
- file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align);
+ file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col);
}
sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
@@ -688,7 +690,8 @@ void file_draw_list(const bContext *C, ARegion *ar)
BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str);
}
file_draw_string(
- sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
+ sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h,
+ align, text_col);
}
sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
@@ -699,10 +702,12 @@ void file_draw_list(const bContext *C, ARegion *ar)
NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str);
}
file_draw_string(
- sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h, align);
+ sx, sy, file->entry->date_str, layout->column_widths[COLUMN_DATE], layout->tile_h,
+ align, text_col);
sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
file_draw_string(
- sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h, align);
+ sx, sy, file->entry->time_str, layout->column_widths[COLUMN_TIME], layout->tile_h,
+ align, text_col);
sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
}
else {
@@ -717,7 +722,8 @@ void file_draw_list(const bContext *C, ARegion *ar)
BLI_filelist_entry_size_to_string(NULL, file->entry->size, small_size, file->entry->size_str);
}
file_draw_string(
- sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
+ sx, sy, file->entry->size_str, layout->column_widths[COLUMN_SIZE], layout->tile_h,
+ align, text_col);
}
sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index f12db310856..70d3fad9554 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -53,7 +53,7 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
-#include "BIF_gl.h"
+#include "GPU_immediate.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -265,43 +265,52 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* only free grid after drawing data, as we need to use it to determine sampling rate */
UI_view2d_grid_free(grid);
-
- /* horizontal component of value-cursor (value line before the current frame line) */
- if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) {
- float y = sipo->cursorVal;
-
- /* Draw a green line to indicate the cursor value */
- UI_ThemeColorShadeAlpha(TH_CFRAME, -10, -50);
- glEnable(GL_BLEND);
- glLineWidth(2.0);
+ if (((sipo->flag & SIPO_NODRAWCURSOR) == 0) || (sipo->mode == SIPO_MODE_DRIVERS)) {
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
- glBegin(GL_LINES);
- glVertex2f(v2d->cur.xmin, y);
- glVertex2f(v2d->cur.xmax, y);
- glEnd();
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glDisable(GL_BLEND);
- }
-
- /* current frame or vertical component of vertical component of the cursor */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- /* cursor x-value */
- float x = sipo->cursorTime;
-
- /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */
- UI_ThemeColorShadeAlpha(TH_CFRAME, -40, -50);
- glEnable(GL_BLEND);
- glLineWidth(2.0);
-
- glBegin(GL_LINES);
- glVertex2f(x, v2d->cur.ymin);
- glVertex2f(x, v2d->cur.ymax);
- glEnd();
+ /* horizontal component of value-cursor (value line before the current frame line) */
+ if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) {
+
+ float y = sipo->cursorVal;
+
+ /* Draw a green line to indicate the cursor value */
+ immUniformThemeColorShadeAlpha(TH_CFRAME, -10, -50);
+ glEnable(GL_BLEND);
+ glLineWidth(2.0);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, v2d->cur.xmin, y);
+ immVertex2f(pos, v2d->cur.xmax, y);
+ immEnd();
- glDisable(GL_BLEND);
+ glDisable(GL_BLEND);
+ }
+
+ /* current frame or vertical component of vertical component of the cursor */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ /* cursor x-value */
+ float x = sipo->cursorTime;
+
+ /* to help differentiate this from the current frame, draw slightly darker like the horizontal one */
+ immUniformThemeColorShadeAlpha(TH_CFRAME, -40, -50);
+ glEnable(GL_BLEND);
+ glLineWidth(2.0);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, x, v2d->cur.ymin);
+ immVertex2f(pos, x, v2d->cur.ymax);
+ immEnd();
+
+ glDisable(GL_BLEND);
+ }
+
+ immUnbindProgram();
}
- else {
+
+ if (sipo->mode != SIPO_MODE_DRIVERS) {
/* current frame */
if (sipo->flag & SIPO_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
if ((sipo->flag & SIPO_NODRAWCFRANUM) == 0) flag |= DRAWCFRA_SHOW_NUMBOX;
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 8dc6c4229b2..435d9b2ee26 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -269,9 +269,9 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
stats->tottri = ob->sculpt->bm->totface;
}
-static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
+static void stats_dupli_object(BaseLegacy *base, Object *ob, SceneStats *stats)
{
- if (base->flag & SELECT) stats->totobjsel++;
+ if (base->flag_legacy & SELECT) stats->totobjsel++;
if (ob->transflag & OB_DUPLIPARTS) {
/* Dupli Particles */
@@ -300,7 +300,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
}
}
- stats_object(ob, base->flag & SELECT, 1, stats);
+ stats_object(ob, base->flag_legacy & SELECT, 1, stats);
stats->totobj++;
}
else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) {
@@ -316,23 +316,23 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
}
stats->totobj += tot;
- stats_object(ob, base->flag & SELECT, tot, stats);
+ stats_object(ob, base->flag_legacy & SELECT, tot, stats);
}
else if (ob->transflag & OB_DUPLIFRAMES) {
/* Dupli Frames */
int tot = count_duplilist(ob);
stats->totobj += tot;
- stats_object(ob, base->flag & SELECT, tot, stats);
+ stats_object(ob, base->flag_legacy & SELECT, tot, stats);
}
else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
/* Dupli Group */
int tot = count_duplilist(ob);
stats->totobj += tot;
- stats_object(ob, base->flag & SELECT, tot, stats);
+ stats_object(ob, base->flag_legacy & SELECT, tot, stats);
}
else {
/* No Dupli */
- stats_object(ob, base->flag & SELECT, 1, stats);
+ stats_object(ob, base->flag_legacy & SELECT, 1, stats);
stats->totobj++;
}
}
@@ -348,7 +348,7 @@ static void stats_update(Scene *scene)
{
SceneStats stats = {0};
Object *ob = (scene->basact) ? scene->basact->object : NULL;
- Base *base;
+ BaseLegacy *base;
if (scene->obedit) {
/* Edit Mode */
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index d3c8fed5fc1..8ee488ac591 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -200,17 +200,15 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
immUnbindProgram();
}
- glColor3ubv(fg);
-
/* last part needs no clipping */
BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
+ BLF_color3ubv(cdc->font_id, fg);
BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
console_step_sel(cdc, -initial_offset);
// glColor4ub(255, 0, 0, 96); // debug
console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
- glColor3ubv(fg);
}
cdc->xy[1] += cdc->lheight;
@@ -226,7 +224,6 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
console_step_sel(cdc, len);
// glColor4ub(0, 255, 0, 96); // debug
console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
- glColor3ubv(fg);
}
cdc->xy[1] += cdc->lheight;
@@ -254,8 +251,6 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
immUnbindProgram();
}
- glColor3ubv(fg);
-
BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth);
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 3de44174d6a..f1a08a45c29 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -460,7 +460,7 @@ static void set_sca_ob(Object *ob)
static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag)
{
- Base *base;
+ BaseLegacy *base;
Main *bmain= CTX_data_main(C);
Scene *scene= CTX_data_scene(C);
Object *ob, *obt, *obact= CTX_data_active_object(C);
@@ -491,7 +491,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf
base= FIRSTBASE;
while (base) {
if (base->lay & lay) {
- if (base->flag & SELECT) {
+ if (base->flag_legacy & SELECT) {
if (scavisflag & BUTS_SENS_SEL) base->object->scavisflag |= OB_VIS_SENS;
if (scavisflag & BUTS_CONT_SEL) base->object->scavisflag |= OB_VIS_CONT;
if (scavisflag & BUTS_ACT_SEL) base->object->scavisflag |= OB_VIS_ACT;
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index e9c46e9d04b..48e822ef876 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -45,6 +45,7 @@
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_report.h"
@@ -125,7 +126,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
{
bDopeSheet *ads = (bDopeSheet *)ac->data;
Scene *sce = (Scene *)ads->source;
- Base *base = (Base *)ale->data;
+ BaseLegacy *base = (BaseLegacy *)ale->data;
Object *ob = base->object;
AnimData *adt = ob->adt;
@@ -133,24 +134,24 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
- base->flag ^= SELECT;
- ob->flag = base->flag;
+ base->flag_legacy ^= SELECT;
+ BKE_scene_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
- Base *b;
+ BaseLegacy *b;
/* deselect all */
/* TODO: should this deselect all other types of channels too? */
for (b = sce->base.first; b; b = b->next) {
- b->flag &= ~SELECT;
- b->object->flag = b->flag;
+ b->flag_legacy &= ~SELECT;
+ BKE_scene_base_flag_sync_from_base(b);
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
}
/* select object now */
- base->flag |= SELECT;
+ base->flag_legacy |= SELECT;
ob->flag |= SELECT;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index a9b8bfd08c8..e744a39fde9 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -54,7 +54,6 @@
#include "ED_anim_api.h"
#include "ED_keyframes_draw.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "GPU_immediate.h"
@@ -101,50 +100,68 @@ void nla_action_get_color(AnimData *adt, bAction *act, float color[4])
}
/* draw the keyframes in the specified Action */
-static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
+static void nla_action_draw_keyframes(AnimData *adt, bAction *act, float y, float ymin, float ymax)
{
- DLRBT_Tree keys;
- ActKeyColumn *ak;
- float xscale, f1, f2;
- float color[4];
-
/* get a list of the keyframes with NLA-scaling applied */
+ DLRBT_Tree keys;
BLI_dlrbTree_init(&keys);
action_to_keylist(adt, act, &keys, NULL);
BLI_dlrbTree_linkedlist_sync(&keys);
-
- if (ELEM(NULL, act, keys.first))
+
+ if (!(act && keys.first))
return;
-
+
/* draw a darkened region behind the strips
* - get and reset the background color, this time without the alpha to stand out better
* (amplified alpha is used instead)
*/
+ float color[4];
nla_action_get_color(adt, act, color);
color[3] *= 2.5f;
-
- glColor4fv(color);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+
+ immUniformColor4fv(color);
+
/* - draw a rect from the first to the last frame (no extra overlaps for now)
* that is slightly stumpier than the track background (hardcoded 2-units here)
*/
- f1 = ((ActKeyColumn *)keys.first)->cfra;
- f2 = ((ActKeyColumn *)keys.last)->cfra;
-
- glRectf(f1, ymin + 2, f2, ymax - 2);
-
-
- /* get View2D scaling factor */
- UI_view2d_scale_get(v2d, &xscale, NULL);
-
- /* for now, color is hardcoded to be black */
- glColor3f(0.0f, 0.0f, 0.0f);
-
- /* just draw each keyframe as a simple dot (regardless of the selection status)
- * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
- */
- for (ak = keys.first; ak; ak = ak->next)
- draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f);
-
+ float f1 = ((ActKeyColumn *)keys.first)->cfra;
+ float f2 = ((ActKeyColumn *)keys.last)->cfra;
+
+ immRectf(pos_id, f1, ymin + 2, f2, ymax - 2);
+ immUnbindProgram();
+
+ /* count keys before drawing */
+ unsigned int key_ct = 0;
+ for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) {
+ key_ct++;
+ }
+
+ if (key_ct > 0) {
+ format = immVertexFormat();
+ pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT);
+ unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+ unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(PRIM_POINTS, key_ct);
+
+ /* - disregard the selection status of keyframes so they draw a certain way
+ * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
+ */
+ for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) {
+ draw_keyframe_shape(ak->cfra, y, 3.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f,
+ pos_id, size_id, color_id, outline_color_id);
+ }
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+ }
+
/* free icons */
BLI_dlrbTree_free(&keys);
}
@@ -152,57 +169,55 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d,
/* Strip Markers ------------------------ */
/* Markers inside an action strip */
-static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
+static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, int shade, unsigned int pos)
{
- bAction *act = strip->act;
- TimeMarker *marker;
-
- if (ELEM(NULL, strip->act, strip->act->markers.first))
+ const bAction *act = strip->act;
+
+ if (!(act && act->markers.first))
return;
-
- for (marker = act->markers.first; marker; marker = marker->next) {
+
+ immUniformThemeColorShade(TH_STRIP_SELECT, shade);
+
+ immBeginAtMost(PRIM_POINTS, BLI_listbase_count(&act->markers));
+ for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) {
float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP);
-
+
/* just a simple line for now */
- // XXX: draw a triangle instead...
- fdrawline(frame, yminc + 1, frame, ymaxc - 1);
+ /* XXX: draw a triangle instead... */
+ immVertex2f(pos, frame, yminc + 1);
+ immVertex2f(pos, frame, ymaxc - 1);
}
}
+ immEnd();
}
/* Markers inside a NLA-Strip */
-static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
+static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos)
{
- glLineWidth(2.0);
+ glLineWidth(2.0f);
if (strip->type == NLASTRIP_TYPE_CLIP) {
/* try not to be too conspicuous, while being visible enough when transforming */
- if (strip->flag & NLASTRIP_FLAG_SELECT)
- UI_ThemeColorShade(TH_STRIP_SELECT, -60);
- else
- UI_ThemeColorShade(TH_STRIP_SELECT, -40);
-
+ int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40;
+
setlinestyle(3);
/* just draw the markers in this clip */
- nla_actionclip_draw_markers(strip, yminc, ymaxc);
+ nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, pos);
setlinestyle(0);
}
else if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
/* just a solid color, so that it is very easy to spot */
- UI_ThemeColorShade(TH_STRIP_SELECT, 20);
-
+ int shade = 20;
/* draw the markers in the first level of strips only (if they are actions) */
for (NlaStrip *nls = strip->strips.first; nls; nls = nls->next) {
if (nls->type == NLASTRIP_TYPE_CLIP) {
- nla_actionclip_draw_markers(nls, yminc, ymaxc);
+ nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, pos);
}
}
}
-
- glLineWidth(1.0);
}
/* Strips (Proper) ---------------------- */
@@ -270,12 +285,8 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col
}
/* helper call for drawing influence/time control curves for a given NLA-strip */
-static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
+static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos)
{
-
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(0.7f, 0.7f, 0.7f, 1.0f);
const float yheight = ymaxc - yminc;
@@ -290,13 +301,13 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
float cfra;
/* plot the curve (over the strip's main region) */
- immBegin(GL_LINE_STRIP, abs(strip->end - strip->start + 1));
+ immBegin(GL_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
/* sample at 1 frame intervals, and draw
* - min y-val is yminc, max is y-maxc, so clamp in those regions
*/
for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
- float y = evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range
+ float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
immVertex2f(pos, cfra, ((y * yheight) + yminc));
}
@@ -330,20 +341,20 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
/* turn off AA'd lines */
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
-
- //Unbind GPU_SHADER_2D_UNIFORM_COLOR
- immUnbindProgram();
}
/* main call for drawing a single NLA-strip */
static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
{
const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
- float color[3];
-
+ float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
/* get color of strip */
nla_strip_get_color_inside(adt, strip, color);
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw extrapolation info first (as backdrop)
* - but this should only be drawn if track has some contribution
*/
@@ -351,7 +362,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* enable transparency... */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-
+
switch (strip->extendmode) {
/* since this does both sides, only do the 'before' side, and leave the rest to the next case */
case NLASTRIP_EXTEND_HOLD:
@@ -360,15 +371,10 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
*/
if (strip->prev == NULL) {
/* set the drawing color to the color of the strip, but with very faint alpha */
- glColor4f(color[0], color[1], color[2], 0.15f);
-
+ immUniformColor3fvAlpha(color, 0.15f);
+
/* draw the rect to the edge of the screen */
- glBegin(GL_QUADS);
- glVertex2f(v2d->cur.xmin, yminc);
- glVertex2f(v2d->cur.xmin, ymaxc);
- glVertex2f(strip->start, ymaxc);
- glVertex2f(strip->start, yminc);
- glEnd();
+ immRectf(pos, v2d->cur.xmin, yminc, strip->start, ymaxc);
}
/* fall-through */
@@ -377,118 +383,132 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* only need to try and draw if the next strip doesn't occur immediately after */
if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) {
/* set the drawing color to the color of the strip, but this time less faint */
- glColor4f(color[0], color[1], color[2], 0.3f);
+ immUniformColor3fvAlpha(color, 0.3f);
/* draw the rect to the next strip or the edge of the screen */
- glBegin(GL_QUADS);
- glVertex2f(strip->end, yminc);
- glVertex2f(strip->end, ymaxc);
-
- if (strip->next) {
- glVertex2f(strip->next->start, ymaxc);
- glVertex2f(strip->next->start, yminc);
- }
- else {
- glVertex2f(v2d->cur.xmax, ymaxc);
- glVertex2f(v2d->cur.xmax, yminc);
- }
- glEnd();
+ float x2 = strip->next ? strip->next->start : v2d->cur.xmax;
+ immRectf(pos, strip->end, yminc, x2, ymaxc);
}
break;
}
-
+
glDisable(GL_BLEND);
}
-
-
+
+
/* draw 'inside' of strip itself */
if (non_solo == 0) {
+ immUnbindProgram();
+
/* strip is in normal track */
- glColor3fv(color);
UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */
-
- UI_draw_roundbox_shade_x(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
+ UI_draw_roundbox_shade_x(GL_TRIANGLE_FAN, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color);
+
+ /* restore current vertex format & program (roundbox trashes it) */
+ pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
}
else {
/* strip is in disabled track - make less visible */
- glColor4f(color[0], color[1], color[2], 0.1f);
+ immUniformColor3fvAlpha(color, 0.1f);
glEnable(GL_BLEND);
- glRectf(strip->start, yminc, strip->end, ymaxc);
+ immRectf(pos, strip->start, yminc, strip->end, ymaxc);
glDisable(GL_BLEND);
}
-
-
+
+
/* draw strip's control 'curves'
* - only if user hasn't hidden them...
*/
if ((snla->flag & SNLA_NOSTRIPCURVES) == 0)
- nla_draw_strip_curves(strip, yminc, ymaxc);
-
-
+ nla_draw_strip_curves(strip, yminc, ymaxc, pos);
+
+
/* draw markings indicating locations of local markers (useful for lining up different actions) */
if ((snla->flag & SNLA_NOLOCALMARKERS) == 0)
- nla_strip_draw_markers(strip, yminc, ymaxc);
-
- /* draw strip outline
+ nla_strip_draw_markers(strip, yminc, ymaxc, pos);
+
+ immUnbindProgram();
+
+ /* draw strip outline
* - color used here is to indicate active vs non-active
*/
if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
/* strip should appear 'sunken', so draw a light border around it */
- glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors
+ color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */
+ color[1] = 1.0f;
+ color[2] = 0.9f;
}
else {
/* strip should appear to stand out, so draw a dark border around it */
- glColor3f(0.0f, 0.0f, 0.0f);
+ color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */
}
-
+
/* - line style: dotted for muted */
if ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED))
setlinestyle(4);
-
+
/* draw outline */
- UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
-
+ UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color);
+
+ /* restore current vertex format & program (roundbox trashes it) */
+ pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3fv(color);
+
/* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f) == 0) {
float repeatLen = (strip->actend - strip->actstart) * strip->scale;
- int i;
-
+
/* only draw lines for whole-numbered repeats, starting from the first full-repeat
* up to the last full repeat (but not if it lies on the end of the strip)
*/
- for (i = 1; i < strip->repeat; i++) {
+ immBeginAtMost(PRIM_LINES, 2 * (strip->repeat - 1));
+ for (int i = 1; i < strip->repeat; i++) {
float repeatPos = strip->start + (repeatLen * i);
-
+
/* don't draw if line would end up on or after the end of the strip */
- if (repeatPos < strip->end)
- fdrawline(repeatPos, yminc + 4, repeatPos, ymaxc - 4);
+ if (repeatPos < strip->end) {
+ immVertex2f(pos, repeatPos, yminc + 4);
+ immVertex2f(pos, repeatPos, ymaxc - 4);
+ }
}
+ immEnd();
}
/* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */
else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
- NlaStrip *cs;
- float y = (ymaxc - yminc) / 2.0f + yminc;
-
+ float y = (ymaxc - yminc) * 0.5f + yminc;
+
+ immBeginAtMost(PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); /* up to 2 lines per strip */
+
/* only draw first-level of child-strips, but don't draw any lines on the endpoints */
- for (cs = strip->strips.first; cs; cs = cs->next) {
+ for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) {
/* draw start-line if not same as end of previous (and only if not the first strip)
* - on upper half of strip
*/
- if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0)
- fdrawline(cs->start, y, cs->start, ymaxc);
-
+ if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) {
+ immVertex2f(pos, cs->start, y);
+ immVertex2f(pos, cs->start, ymaxc);
+ }
+
/* draw end-line if not the last strip
* - on lower half of strip
*/
- if (cs->next)
- fdrawline(cs->end, yminc, cs->end, y);
+ if (cs->next) {
+ immVertex2f(pos, cs->end, yminc);
+ immVertex2f(pos, cs->end, y);
+ }
}
+
+ immEnd();
}
-
+
/* reset linestyle */
setlinestyle(0);
-}
+ immUnbindProgram();
+}
/* add the relevant text to the cache of text-strings to draw in pixelspace */
static void nla_draw_strip_text(
@@ -499,7 +519,6 @@ static void nla_draw_strip_text(
char str[256];
size_t str_len;
char col[4];
- rctf rect;
/* just print the name and the range */
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
@@ -526,12 +545,14 @@ static void nla_draw_strip_text(
/* set bounding-box for text
* - padding of 2 'units' on either side
*/
- // TODO: make this centered?
- rect.xmin = xminc;
- rect.ymin = yminc;
- rect.xmax = xmaxc;
- rect.ymax = ymaxc;
-
+ /* TODO: make this centered? */
+ rctf rect = {
+ .xmin = xminc,
+ .ymin = yminc,
+ .xmax = xmaxc,
+ .ymax = ymaxc
+ };
+
/* add this string to the cache of texts to draw */
UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
}
@@ -544,9 +565,7 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */
const char col[4] = {220, 220, 220, 255}; /* light gray */
char numstr[32];
- size_t numstr_len;
-
-
+
/* Always draw times above the strip, whereas sequencer drew below + above.
* However, we should be fine having everything on top, since these tend to be
* quite spaced out.
@@ -554,9 +573,9 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
* while also preserving some accuracy, since we do use floats
*/
/* start frame */
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start);
+ size_t numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start);
UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col);
-
+
/* end frame */
numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end);
UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col);
@@ -566,20 +585,14 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
View2D *v2d = &ar->v2d;
- float y = 0.0f;
- size_t items;
- int height;
const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
const float text_margin_x = (8 * UI_DPI_FAC) * pixelx;
/* build list of channels to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ ListBase anim_data = {NULL, NULL};
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Update max-extent of channels here (taking into account scrollers):
* - this is done to allow the channel list to be scrollable, but must be done here
@@ -587,16 +600,16 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
+ int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
v2d->tot.ymin = (float)(-height);
/* loop through channels, and set up drawing depending on their type */
- y = (float)(-NLACHANNEL_HEIGHT(snla));
+ float y = (float)(-NLACHANNEL_HEIGHT(snla));
- for (ale = anim_data.first; ale; ale = ale->next) {
+ for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
@@ -610,11 +623,10 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
AnimData *adt = ale->adt;
NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
- int index;
/* draw each strip in the track (if visible) */
- for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) {
+ int index = 1;
+ for (NlaStrip *strip = nlt->strips.first; strip; strip = strip->next, index++) {
if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
const float xminc = strip->start + text_margin_x;
const float xmaxc = strip->end + text_margin_x;
@@ -639,45 +651,60 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
case ANIMTYPE_NLAACTION:
{
AnimData *adt = ale->adt;
- float color[4];
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
* and a second darker rect within which we draw keyframe indicator dots if there's data
*/
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-
+
/* get colors for drawing */
+ float color[4];
nla_action_get_color(adt, ale->data, color);
- glColor4fv(color);
-
+ immUniformColor4fv(color);
+
/* draw slightly shifted up for greater separation from standard channels,
* but also slightly shorter for some more contrast when viewing the strips
*/
- glRectf(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
-
- /* draw keyframes in the action */
- nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
+ immRectf(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
/* draw 'embossed' lines above and below the strip for effect */
/* white base-lines */
glLineWidth(2.0f);
- glColor4f(1.0f, 1.0f, 1.0f, 0.3);
- fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
-
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3);
+ immBegin(PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immEnd();
+
/* black top-lines */
glLineWidth(1.0f);
- glColor3f(0.0f, 0.0f, 0.0f);
- fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
-
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immBegin(PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immEnd();
+
+ /* TODO: these lines but better --^ */
+
+ immUnbindProgram();
+
+ /* draw keyframes in the action */
+ nla_action_draw_keyframes(adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
+
glDisable(GL_BLEND);
break;
}
}
}
-
+
/* adjust y-position for next one */
y -= NLACHANNEL_STEP(snla);
}
@@ -693,17 +720,14 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
- int filter;
SpaceNla *snla = (SpaceNla *)ac->sl;
View2D *v2d = &ar->v2d;
float y = 0.0f;
- size_t items;
- int height;
/* build list of channels to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Update max-extent of channels here (taking into account scrollers):
* - this is done to allow the channel list to be scrollable, but must be done here
@@ -711,7 +735,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
+ int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index e02c69ea857..5940ed5f0c1 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3619,27 +3619,27 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
// node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
}
-void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border)
+void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos)
{
- glBegin(GL_LINES);
+ immBegin(GL_LINES, 4);
if (border & (NODE_LEFT | NODE_RIGHT)) {
- glVertex2f(cent[0], v2d->cur.ymin);
- glVertex2f(cent[0], v2d->cur.ymax);
+ immVertex2f(pos, cent[0], v2d->cur.ymin);
+ immVertex2f(pos, cent[0], v2d->cur.ymax);
}
else {
- glVertex2f(cent[0], cent[1] - size);
- glVertex2f(cent[0], cent[1] + size);
+ immVertex2f(pos, cent[0], cent[1] - size);
+ immVertex2f(pos, cent[0], cent[1] + size);
}
if (border & (NODE_TOP | NODE_BOTTOM)) {
- glVertex2f(v2d->cur.xmin, cent[1]);
- glVertex2f(v2d->cur.xmax, cent[1]);
+ immVertex2f(pos, v2d->cur.xmin, cent[1]);
+ immVertex2f(pos, v2d->cur.xmax, cent[1]);
}
else {
- glVertex2f(cent[0] - size, cent[1]);
- glVertex2f(cent[0] + size, cent[1]);
+ immVertex2f(pos, cent[0] - size, cent[1]);
+ immVertex2f(pos, cent[0] + size, cent[1]);
}
- glEnd();
+ immEnd();
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 2a0593e6a0d..80b19176c90 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -1269,7 +1269,7 @@ static void draw_tree_path(SpaceNode *snode)
ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info));
}
@@ -1315,7 +1315,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
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, color);
+ UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, 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_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 998dad6466b..d15c3d67d45 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -51,6 +51,7 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -174,116 +175,6 @@ static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_
}
-static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag,
- bool state, bool deselect, const char *rnapropname)
-{
- Main *bmain = CTX_data_main(C);
- Object *ob;
-
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (BKE_object_is_child_recursive(ob_parent, ob)) {
- /* only do if child object is selectable */
- if ((flag == OB_RESTRICT_SELECT) || (ob->restrictflag & OB_RESTRICT_SELECT) == 0) {
- if (state) {
- ob->restrictflag |= flag;
- if (deselect) {
- ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
- }
- }
- else {
- ob->restrictflag &= ~flag;
- }
- }
-
- if (rnapropname) {
- PointerRNA ptr;
- PropertyRNA *prop;
- ID *id;
- bAction *action;
- FCurve *fcu;
- bool driven, special;
-
- RNA_id_pointer_create(&ob->id, &ptr);
- prop = RNA_struct_find_property(&ptr, rnapropname);
- fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, &special);
-
- if (fcu && !driven) {
- id = ptr.id.data;
- if (autokeyframe_cfra_can_key(scene, id)) {
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- eInsertKeyFlags key_flag = ANIM_get_keyframing_flags(scene, 1);
-
- fcu->flag &= ~FCURVE_SELECTED;
- insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path, fcu->array_index, CFRA, ts->keyframe_type, key_flag);
- /* Assuming this is not necessary here, since 'ancestor' object button will do it anyway. */
- /* WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); */
- }
- }
- }
- }
- }
-}
-
-static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
-{
- Scene *scene = (Scene *)poin;
- Object *ob = (Object *)poin2;
-
- if (!common_restrict_check(C, ob)) return;
-
- /* deselect objects that are invisible */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
- /* Ouch! There is no backwards pointer from Object to Base,
- * so have to do loop to find it. */
- ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
- }
-
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW,
- (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true, "hide");
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
-}
-
-static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
-{
- Scene *scene = (Scene *)poin;
- Object *ob = (Object *)poin2;
-
- if (!common_restrict_check(C, ob)) return;
-
- /* if select restriction has just been turned on */
- if (ob->restrictflag & OB_RESTRICT_SELECT) {
- /* Ouch! There is no backwards pointer from Object to Base,
- * so have to do loop to find it. */
- ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
- }
-
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT,
- (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true, NULL);
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
-}
-
-static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2)
-{
- Object *ob = (Object *)poin2;
-
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_child(C, (Scene *)poin, ob, OB_RESTRICT_RENDER,
- (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false, "hide_render");
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin);
-}
-
static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin);
@@ -357,96 +248,32 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-static int group_restrict_flag(Group *gr, int flag)
+static void restrictbutton_collection_hide_cb(bContext *C, void *poin, void *poin2)
{
- GroupObject *gob;
+ Scene *scene = poin;
+ LayerCollection *collection = poin2;
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, collection);
-#ifdef USE_GROUP_SELECT
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if ((gob->ob->restrictflag & flag) == 0)
- return 0;
- }
- return 1;
-#else
- /* weak but fast */
- if ((gob = gr->gobject.first))
- if ((gob->ob->restrictflag & flag) == 0)
- return 0;
- return 1;
-#endif
-}
-
-static int group_select_flag(Group *gr)
-{
- GroupObject *gob;
-
-#ifdef USE_GROUP_SELECT
- for (gob = gr->gobject.first; gob; gob = gob->next)
- if ((gob->ob->flag & SELECT))
- return 1;
-
- return 0;
-#else
- /* weak but fast */
- if ((gob = gr->gobject.first))
- if (gob->ob->flag & SELECT)
- return 1;
- return 0;
-#endif
+ /* hide and deselect bases that are directly influenced by this LayerCollection */
+ BKE_scene_layer_base_flag_recalculate(sl);
+ BKE_scene_layer_engine_settings_collection_recalculate(sl, collection);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
}
-void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag)
+static void restrictbutton_collection_hide_select_cb(bContext *C, void *poin, void *poin2)
{
- Scene *scene = (Scene *)poin;
- GroupObject *gob;
- Group *gr = (Group *)poin2;
+ Scene *scene = poin;
+ LayerCollection *collection = poin2;
- if (group_restrict_flag(gr, flag)) {
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (ID_IS_LINKED_DATABLOCK(gob->ob))
- continue;
+ if ((collection->flag & COLLECTION_SELECTABLE) == 0) {
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, collection);
- gob->ob->restrictflag &= ~flag;
-
- if (flag == OB_RESTRICT_VIEW)
- if (gob->ob->flag & SELECT)
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT);
- }
+ /* deselect bases that are directly influenced by this LayerCollection */
+ BKE_scene_layer_base_flag_recalculate(sl);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
}
- else {
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (ID_IS_LINKED_DATABLOCK(gob->ob))
- continue;
-
- /* not in editmode */
- if (scene->obedit != gob->ob) {
- gob->ob->restrictflag |= flag;
-
- if (ELEM(flag, OB_RESTRICT_SELECT, OB_RESTRICT_VIEW)) {
- if ((gob->ob->flag & SELECT)) {
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT);
- }
- }
- }
- }
- }
-}
-
-static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2)
-{
- restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW);
- WM_event_add_notifier(C, NC_GROUP, NULL);
- DAG_id_type_tag(CTX_data_main(C), ID_OB);
-}
-static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2)
-{
- restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_SELECT);
- WM_event_add_notifier(C, NC_GROUP, NULL);
-}
-static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2)
-{
- restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_RENDER);
- WM_event_add_notifier(C, NC_GROUP, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
}
static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
@@ -468,6 +295,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
BLI_mempool *ts = soops->treestore;
TreeStoreElem *tselem = tsep;
@@ -529,7 +357,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
ED_armature_bone_rename(obedit->data, oldname, newname);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, OBACT_NEW);
}
break;
}
@@ -541,8 +369,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
char newname[sizeof(bone->name)];
/* always make current object active */
- tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, true);
- ob = OBACT;
+ tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, true);
+ ob = OBACT_NEW;
/* restore bone name */
BLI_strncpy(newname, bone->name, sizeof(bone->name));
@@ -558,8 +386,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
char newname[sizeof(pchan->name)];
/* always make current pose-bone active */
- tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, true);
- ob = OBACT;
+ tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, true);
+ ob = OBACT_NEW;
BLI_assert(ob->type == OB_ARMATURE);
@@ -605,7 +433,6 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
TreeElement *te;
TreeStoreElem *tselem;
Object *ob = NULL;
- Group *gr = NULL;
PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render;
@@ -619,73 +446,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
- /* objects have toggle-able restriction flags */
- if (tselem->type == 0 && te->idcode == ID_OB) {
- PointerRNA ptr;
-
- ob = (Object *)tselem->id;
- RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, object_prop_hide, -1, 0, 0, -1, -1,
- TIP_("Restrict viewport visibility (Ctrl - Recursive)"));
- UI_but_func_set(bt, restrictbutton_view_cb, scene, ob);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, object_prop_hide_select, -1, 0, 0, -1, -1,
- TIP_("Restrict viewport selection (Ctrl - Recursive)"));
- UI_but_func_set(bt, restrictbutton_sel_cb, scene, ob);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, object_prop_hide_render, -1, 0, 0, -1, -1,
- TIP_("Restrict rendering (Ctrl - Recursive)"));
- UI_but_func_set(bt, restrictbutton_rend_cb, scene, ob);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- }
- if (tselem->type == 0 && te->idcode == ID_GR) {
- int restrict_bool;
- int but_flag = UI_BUT_DRAG_LOCK;
- gr = (Group *)tselem->id;
-
- if (ID_IS_LINKED_DATABLOCK(gr))
- but_flag |= UI_BUT_DISABLED;
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
- bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_gr_restrict_view, scene, gr);
- UI_but_flag_enable(bt, but_flag);
-
- restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
- bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Restrict/Allow selection in the 3D View"));
- UI_but_func_set(bt, restrictbutton_gr_restrict_select, scene, gr);
- UI_but_flag_enable(bt, but_flag);
-
- restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
- bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
- UI_but_func_set(bt, restrictbutton_gr_restrict_render, scene, gr);
- UI_but_flag_enable(bt, but_flag);
-
- UI_block_emboss_set(block, UI_EMBOSS);
- }
/* scene render layers and passes have toggle-able flags too! */
- else if (tselem->type == TSE_R_LAYER) {
+ if (tselem->type == TSE_R_LAYER) {
UI_block_emboss_set(block, UI_EMBOSS_NONE);
bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
@@ -807,6 +569,27 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS);
}
+ else if (tselem->type == TSE_COLLECTION) {
+ LayerCollection *collection = te->directdata;
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VISIBLE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow 3D View visibility of objects in the collection"));
+ UI_but_func_set(bt, restrictbutton_collection_hide_cb, scene, collection);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow 3D View selection of objects in the collection"));
+ UI_but_func_set(bt, restrictbutton_collection_hide_select_cb, scene, collection);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
}
if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
@@ -1350,7 +1133,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
}
-static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level,
+static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, SpaceOops *soops, ListBase *lb, int level,
int xmax, int *offsx, int ys)
{
TreeElement *te;
@@ -1371,17 +1154,17 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
/* active blocks get white circle */
if (tselem->type == 0) {
if (te->idcode == ID_OB) {
- active = (OBACT == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
+ active = (OBACT_NEW == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
}
else if (scene->obedit && scene->obedit->data == tselem->id) {
active = OL_DRAWSEL_NORMAL;
}
else {
- active = tree_element_active(C, scene, soops, te, OL_SETSEL_NONE, false);
+ active = tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NONE, false);
}
}
else {
- active = tree_element_type_active(NULL, scene, soops, te, tselem, OL_SETSEL_NONE, false);
+ active = tree_element_type_active(NULL, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false);
}
if (active != OL_DRAWSEL_NONE) {
@@ -1410,7 +1193,7 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
/* this tree element always has same amount of branches, so don't draw */
if (tselem->type != TSE_R_LAYER)
- outliner_draw_iconrow(C, block, scene, soops, &te->subtree, level + 1, xmax, offsx, ys);
+ outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, level + 1, xmax, offsx, ys);
}
}
@@ -1434,7 +1217,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta
static void outliner_draw_tree_element(
- bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ARegion *ar, SpaceOops *soops,
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, SceneLayer *sl, ARegion *ar, SpaceOops *soops,
TreeElement *te, int startx, int *starty, TreeElement **te_edit)
{
TreeElement *ten;
@@ -1467,26 +1250,16 @@ static void outliner_draw_tree_element(
active = OL_DRAWSEL_ACTIVE;
}
}
- else if (te->idcode == ID_GR) {
- Group *gr = (Group *)tselem->id;
- if (group_select_flag(gr)) {
- char col[4];
- UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
- rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha);
-
- active = OL_DRAWSEL_ACTIVE;
- }
- }
else if (te->idcode == ID_OB) {
Object *ob = (Object *)tselem->id;
- if (ob == OBACT || (ob->flag & SELECT)) {
+ if (ob == OBACT_NEW || (ob->flag & SELECT)) {
char col[4] = {0, 0, 0, 0};
/* outliner active ob: always white text, circle color now similar to view3d */
active = OL_DRAWSEL_ACTIVE;
- if (ob == OBACT) {
+ if (ob == OBACT_NEW) {
if (ob->flag & SELECT) {
UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
col[3] = alpha;
@@ -1507,14 +1280,14 @@ static void outliner_draw_tree_element(
active = OL_DRAWSEL_ACTIVE;
}
else {
- if (tree_element_active(C, scene, soops, te, OL_SETSEL_NONE, false)) {
+ if (tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NONE, false)) {
rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
active = OL_DRAWSEL_ACTIVE;
}
}
}
else {
- if (tree_element_type_active(NULL, scene, soops, te, tselem, OL_SETSEL_NONE, false) != OL_DRAWSEL_NONE) {
+ if (tree_element_type_active(NULL, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false) != OL_DRAWSEL_NONE) {
active = OL_DRAWSEL_ACTIVE;
}
rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
@@ -1579,17 +1352,20 @@ static void outliner_draw_tree_element(
/* name */
if ((tselem->flag & TSE_TEXTBUT) == 0) {
+ unsigned char text_col[4];
+
if (active == OL_DRAWSEL_NORMAL) {
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
}
else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
- UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
+ UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_col);
+ text_col[3] = 255;
}
else {
- UI_ThemeColor(TH_TEXT);
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
}
- UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name);
+ UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_col);
}
offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
@@ -1606,16 +1382,23 @@ static void outliner_draw_tree_element(
int tempx = startx + offsx;
/* divider */
- UI_ThemeColorShade(TH_BACK, -40);
- glRecti(tempx - 10.0f * ufac,
- *starty + 4.0f * ufac,
- tempx - 8.0f * ufac,
- *starty + UI_UNIT_Y - 4.0f * ufac);
-
+ {
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ unsigned char col[4];
+ UI_GetThemeColorShade4ubv(TH_BACK, -40, col);
+ immUniformColor4ubv(col);
+ immRecti(pos, tempx - 10.0f * ufac,
+ *starty + 4.0f * ufac,
+ tempx - 8.0f * ufac,
+ *starty + UI_UNIT_Y - 4.0f * ufac);
+ immUnbindProgram();
+ }
glEnable(GL_BLEND);
glPixelTransferf(GL_ALPHA_SCALE, 0.5);
- outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty);
+ outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, 0, xmax, &tempx, *starty);
glPixelTransferf(GL_ALPHA_SCALE, 1.0);
glDisable(GL_BLEND);
@@ -1632,7 +1415,7 @@ static void outliner_draw_tree_element(
*starty -= UI_UNIT_Y;
for (ten = te->subtree.first; ten; ten = ten->next) {
- outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
+ outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
}
}
else {
@@ -1644,14 +1427,14 @@ static void outliner_draw_tree_element(
}
}
-static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty)
+static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx, int *starty)
{
+ if (BLI_listbase_is_empty(lb)) return;
+
TreeElement *te;
TreeStoreElem *tselem;
int y1, y2;
-
- if (BLI_listbase_is_empty(lb)) return;
-
+
y1 = y2 = *starty; /* for vertical lines between objects */
for (te = lb->first; te; te = te->next) {
y2 = *starty;
@@ -1659,25 +1442,35 @@ static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int st
/* horizontal line? */
if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE))
- glRecti(startx, *starty, startx + UI_UNIT_X, *starty - 1);
+ immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1);
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops))
- outliner_draw_hierarchy_lines(soops, &te->subtree, startx + UI_UNIT_X, starty);
+ outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X, starty);
}
/* vertical line */
te = lb->last;
if (te->parent || lb->first != lb->last) {
tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
-
- glRecti(startx, y1 + UI_UNIT_Y, startx + 1, y2);
- }
+ if (tselem->type == 0 && te->idcode == ID_OB)
+ immRecti(pos, startx, y1 + UI_UNIT_Y, startx + 1, y2);
}
}
+static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty)
+{
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ unsigned char col[3];
+ UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
+ immUniformColor3ubv(col);
+ outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, starty);
+ immUnbindProgram();
+}
+
static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
{
TreeElement *te;
@@ -1713,7 +1506,7 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
}
static void outliner_draw_highlights_recursive(
- const ARegion *ar, const SpaceOops *soops, const ListBase *lb,
+ unsigned pos, 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)
{
@@ -1726,29 +1519,29 @@ static void outliner_draw_highlights_recursive(
/* selection status */
if (tselem->flag & TSE_SELECTED) {
- glColor4fv(col_selection);
- glRecti(0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+ immUniformColor4fv(col_selection);
+ immRecti(pos, 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);
+ immUniformColor4fv(col_searchmatch);
+ immRecti(pos, 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);
+ immUniformColor4fv(col_highlight);
+ immRecti(pos, 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);
+ pos, ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch,
+ start_x + UI_UNIT_X, io_start_y);
}
}
}
@@ -1764,13 +1557,17 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx,
col_searchmatch[3] = 0.5f;
glEnable(GL_BLEND);
- outliner_draw_highlights_recursive(ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
- startx, starty);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ outliner_draw_highlights_recursive(pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
+ startx, starty);
+ immUnbindProgram();
glDisable(GL_BLEND);
}
static void outliner_draw_tree(
- bContext *C, uiBlock *block, Scene *scene, ARegion *ar,
+ bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, ARegion *ar,
SpaceOops *soops, const bool has_restrict_icons,
TreeElement **te_edit)
{
@@ -1801,7 +1598,7 @@ static void outliner_draw_tree(
}
// 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_lines(soops, &soops->tree, startx, &starty);
@@ -1810,7 +1607,7 @@ static void outliner_draw_tree(
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
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);
+ outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, te, startx, &starty, te_edit);
}
if (has_restrict_icons) {
@@ -1882,6 +1679,7 @@ void draw_outliner(const bContext *C)
{
Main *mainvar = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1890,7 +1688,7 @@ void draw_outliner(const bContext *C)
TreeElement *te_edit = NULL;
bool has_restrict_icons;
- outliner_build_tree(mainvar, scene, soops); // always
+ outliner_build_tree(mainvar, scene, sl, soops); // always
/* get extents of data */
outliner_height(soops, &soops->tree, &sizey);
@@ -1940,7 +1738,7 @@ 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, has_restrict_icons, &te_edit);
+ outliner_draw_tree((bContext *)C, block, scene, sl, ar, soops, has_restrict_icons, &te_edit);
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
/* draw rna buttons */
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 4dcdcc69d6d..0afaf298264 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -54,6 +54,7 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -882,181 +883,6 @@ int common_restrict_check(bContext *C, Object *ob)
}
/* =============================================== */
-/* Restriction toggles */
-
-/* Toggle Visibility ---------------------------------------- */
-
-void object_toggle_visibility_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Base *base = (Base *)te->directdata;
- Object *ob = (Object *)tselem->id;
-
- if (ID_IS_LINKED_DATABLOCK(tselem->id)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
- return;
- }
-
- /* add check for edit mode */
- if (!common_restrict_check(C, ob)) return;
-
- if (base || (base = BKE_scene_base_find(scene, ob))) {
- if ((base->object->restrictflag ^= OB_RESTRICT_VIEW)) {
- ED_base_object_select(base, BA_DESELECT);
- }
- }
-}
-
-void group_toggle_visibility_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
- restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_VIEW);
-}
-
-static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
-
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb);
-
- DAG_id_type_tag(bmain, ID_OB);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_visibility_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Visibility";
- ot->idname = "OUTLINER_OT_visibility_toggle";
- ot->description = "Toggle the visibility of selected items";
-
- /* callbacks */
- ot->exec = outliner_toggle_visibility_exec;
- ot->poll = ED_operator_outliner_active_no_editobject;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* Toggle Selectability ---------------------------------------- */
-
-void object_toggle_selectability_cb(
- bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Base *base = (Base *)te->directdata;
-
- if (ID_IS_LINKED_DATABLOCK(tselem->id)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
- return;
- }
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base) {
- base->object->restrictflag ^= OB_RESTRICT_SELECT;
- }
-}
-
-void group_toggle_selectability_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
- restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_SELECT);
-}
-
-static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
-
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_selectability_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Selectability";
- ot->idname = "OUTLINER_OT_selectability_toggle";
- ot->description = "Toggle the selectability";
-
- /* callbacks */
- ot->exec = outliner_toggle_selectability_exec;
- ot->poll = ED_operator_outliner_active_no_editobject;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* Toggle Renderability ---------------------------------------- */
-
-void object_toggle_renderability_cb(
- bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Base *base = (Base *)te->directdata;
-
- if (ID_IS_LINKED_DATABLOCK(tselem->id)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
- return;
- }
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base) {
- base->object->restrictflag ^= OB_RESTRICT_RENDER;
- }
-}
-
-void group_toggle_renderability_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
- restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_RENDER);
-}
-
-static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
-
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb);
-
- DAG_id_type_tag(bmain, ID_OB);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene);
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_renderability_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Renderability";
- ot->idname = "OUTLINER_OT_renderability_toggle";
- ot->description = "Toggle the renderability of selected items";
-
- /* callbacks */
- ot->exec = outliner_toggle_renderability_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* =============================================== */
/* Outliner setting toggles */
/* Toggle Expanded (Outliner) ---------------------------------------- */
@@ -1177,14 +1003,14 @@ static int outliner_open_back(TreeElement *te)
static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceOops *so = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
TreeElement *te;
int xdelta, ytop;
- Object *obact = OBACT;
+ Object *obact = OBACT_NEW;
if (!obact)
return OPERATOR_CANCELLED;
@@ -2345,8 +2171,6 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
te = outliner_dropzone_find(soops, fmval, false);
if (te) {
- Base *base;
-
RNA_string_set(op->ptr, "scene", te->name);
scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name);
@@ -2357,16 +2181,26 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- base = ED_object_scene_link(scene, ob);
-
- if (base == NULL) {
+ if (BKE_scene_has_object(scene, ob)) {
return OPERATOR_CANCELLED;
}
- if (scene == CTX_data_scene(C)) {
- /* when linking to an inactive scene don't touch the layer */
- ob->lay = base->lay;
- ED_base_object_select(base, BA_SELECT);
+ SceneCollection *sc;
+ if (scene != CTX_data_scene(C)) {
+ /* when linking to an inactive scene link to the master collection */
+ sc = BKE_collection_master(scene);
+ }
+ else {
+ sc = CTX_data_scene_collection(C);
+ }
+
+ BKE_collection_object_add(scene, sc, ob);
+
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+ if (base) {
+ ED_object_base_select(base, BA_SELECT);
+ }
}
DAG_relations_tag_update(bmain);
@@ -2461,7 +2295,6 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Group *group = NULL;
Object *ob = NULL;
- Scene *scene = CTX_data_scene(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
TreeElement *te = NULL;
@@ -2491,7 +2324,7 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- BKE_group_object_add(group, ob, scene, NULL);
+ BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index f23c294c488..768fe4d8551 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -40,6 +40,7 @@ struct wmOperatorType;
struct TreeStoreElem;
struct bContext;
struct Scene;
+struct SceneLayer;
struct ID;
struct Object;
struct bPoseChannel;
@@ -141,7 +142,7 @@ TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *
TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode);
-void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SpaceOops *soops);
+void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops);
/* outliner_draw.c ---------------------------------------------- */
@@ -150,9 +151,9 @@ void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag);
/* outliner_select.c -------------------------------------------- */
eOLDrawState tree_element_type_active(
- struct bContext *C, struct Scene *scene, struct SpaceOops *soops,
+ struct bContext *C, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops,
TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive);
-eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops,
+eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, struct SceneLayer *sl, SpaceOops *soops,
TreeElement *te, const eOLSetState set, const bool handle_all_types);
int outliner_item_activate_or_toggle_closed(struct bContext *C, int x, int y, bool extend, bool recursive);
@@ -239,10 +240,6 @@ void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot);
void OUTLINER_OT_scroll_page(struct wmOperatorType *ot);
-void OUTLINER_OT_renderability_toggle(struct wmOperatorType *ot);
-void OUTLINER_OT_selectability_toggle(struct wmOperatorType *ot);
-void OUTLINER_OT_visibility_toggle(struct wmOperatorType *ot);
-
void OUTLINER_OT_keyingset_add_selected(struct wmOperatorType *ot);
void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index f0c2d848f7a..5ddfdddc80d 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -71,10 +71,6 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_selected_toggle);
WM_operatortype_append(OUTLINER_OT_expanded_toggle);
- WM_operatortype_append(OUTLINER_OT_renderability_toggle);
- WM_operatortype_append(OUTLINER_OT_selectability_toggle);
- WM_operatortype_append(OUTLINER_OT_visibility_toggle);
-
WM_operatortype_append(OUTLINER_OT_keyingset_add_selected);
WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected);
@@ -143,11 +139,6 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OUTLINER_OT_selected_toggle", AKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_expanded_toggle", AKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_renderability_toggle", RKEY, KM_PRESS, 0, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_selectability_toggle", SKEY, KM_PRESS, 0, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_visibility_toggle", VKEY, KM_PRESS, 0, 0);
-
-
/* keying sets - only for databrowse */
WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index a73e160f357..1fad5f26218 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -46,6 +46,7 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_object.h"
+#include "BKE_layer.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_armature.h"
@@ -73,7 +74,7 @@
/* Outliner Element Selection/Activation on Click */
static eOLDrawState tree_element_active_renderlayer(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Scene *sce;
@@ -99,7 +100,7 @@ static eOLDrawState tree_element_active_renderlayer(
*/
static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select)
{
- Base *base;
+ BaseLegacy *base;
for (base = FIRSTBASE; base; base = base->next) {
Object *ob = base->object;
@@ -135,7 +136,7 @@ static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_p
}
static eOLDrawState tree_element_set_active_object(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops,
TreeElement *te, const eOLSetState set, bool recursive)
{
TreeStoreElem *tselem = TREESTORE(te);
@@ -149,7 +150,7 @@ static eOLDrawState tree_element_set_active_object(
}
else {
ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == OBACT) {
+ if (ob == OBACT_NEW) {
return OL_DRAWSEL_NONE;
}
}
@@ -169,15 +170,15 @@ static eOLDrawState tree_element_set_active_object(
if (base) {
if (set == OL_SETSEL_EXTEND) {
/* swap select */
- if (base->flag & SELECT)
- ED_base_object_select(base, BA_DESELECT);
+ if (base->flag & BASE_SELECTED)
+ ED_object_base_select(base, BA_DESELECT);
else
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
}
else {
/* deleselect all */
- BKE_scene_base_deselect_all(scene);
- ED_base_object_select(base, BA_SELECT);
+ BKE_scene_layer_base_deselect_all(sl);
+ ED_object_base_select(base, BA_SELECT);
}
if (recursive) {
@@ -186,7 +187,7 @@ static eOLDrawState tree_element_set_active_object(
}
if (C) {
- ED_base_object_activate(C, base); /* adds notifier */
+ ED_object_base_activate(C, base); /* adds notifier */
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
}
@@ -198,7 +199,7 @@ static eOLDrawState tree_element_set_active_object(
}
static eOLDrawState tree_element_active_material(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene* UNUSED(scene), SceneLayer *sl, SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
TreeElement *tes;
@@ -207,7 +208,7 @@ static eOLDrawState tree_element_active_material(
/* we search for the object parent */
ob = (Object *)outliner_search_back(soops, te, ID_OB);
// note: ob->matbits can be NULL when a local object points to a library mesh.
- if (ob == NULL || ob != OBACT || ob->matbits == NULL) {
+ if (ob == NULL || ob != OBACT_NEW || ob->matbits == NULL) {
return OL_DRAWSEL_NONE; /* just paranoia */
}
@@ -251,12 +252,12 @@ static eOLDrawState tree_element_active_material(
}
static eOLDrawState tree_element_active_texture(
- bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
+ bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *UNUSED(soops),
TreeElement *te, const eOLSetState set)
{
TreeElement *tep;
TreeStoreElem /* *tselem,*/ *tselemp;
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
SpaceButs *sbuts = NULL;
if (ob == NULL) {
@@ -338,14 +339,14 @@ static eOLDrawState tree_element_active_texture(
static eOLDrawState tree_element_active_lamp(
- bContext *UNUSED(C), Scene *scene, SpaceOops *soops,
+ bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *sl, SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
Object *ob;
/* we search for the object parent */
ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == NULL || ob != OBACT) {
+ if (ob == NULL || ob != OBACT_NEW) {
/* just paranoia */
return OL_DRAWSEL_NONE;
}
@@ -361,7 +362,7 @@ static eOLDrawState tree_element_active_lamp(
}
static eOLDrawState tree_element_active_camera(
- bContext *UNUSED(C), Scene *scene, SpaceOops *soops,
+ bContext *UNUSED(C), Scene *scene, SceneLayer *UNUSED(sl), SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
@@ -374,7 +375,7 @@ static eOLDrawState tree_element_active_camera(
}
static eOLDrawState tree_element_active_world(
- bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
+ bContext *C, Scene *scene, SceneLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
TreeElement *te, const eOLSetState set)
{
TreeElement *tep;
@@ -407,7 +408,7 @@ static eOLDrawState tree_element_active_world(
}
static eOLDrawState tree_element_active_defgroup(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob;
@@ -421,7 +422,7 @@ static eOLDrawState tree_element_active_defgroup(
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
}
else {
- if (ob == OBACT)
+ if (ob == OBACT_NEW)
if (ob->actdef == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
@@ -430,7 +431,7 @@ static eOLDrawState tree_element_active_defgroup(
}
static eOLDrawState tree_element_active_posegroup(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob = (Object *)tselem->id;
@@ -441,7 +442,7 @@ static eOLDrawState tree_element_active_posegroup(
}
}
else {
- if (ob == OBACT && ob->pose) {
+ if (ob == OBACT_NEW && ob->pose) {
if (ob->pose->active_group == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
@@ -451,7 +452,7 @@ static eOLDrawState tree_element_active_posegroup(
}
static eOLDrawState tree_element_active_posechannel(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+ bContext *C, Scene *UNUSED(scene), SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
{
Object *ob = (Object *)tselem->id;
bArmature *arm = ob->data;
@@ -485,7 +486,7 @@ static eOLDrawState tree_element_active_posechannel(
}
}
else {
- if (ob == OBACT && ob->pose) {
+ if (ob == OBACT_NEW && ob->pose) {
if (pchan->bone->flag & BONE_SELECTED) {
return OL_DRAWSEL_NORMAL;
}
@@ -495,14 +496,14 @@ static eOLDrawState tree_element_active_posechannel(
}
static eOLDrawState tree_element_active_bone(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+ bContext *C, SceneLayer *sl, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
{
bArmature *arm = (bArmature *)tselem->id;
Bone *bone = te->directdata;
if (set != OL_SETSEL_NONE) {
if (!(bone->flag & BONE_HIDDEN_P)) {
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
if (ob) {
if (set != OL_SETSEL_EXTEND) {
/* single select forces all other bones to get unselected */
@@ -531,7 +532,7 @@ static eOLDrawState tree_element_active_bone(
}
}
else {
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
if (ob && ob->data == arm) {
if (bone->flag & BONE_SELECTED) {
@@ -604,7 +605,7 @@ static eOLDrawState tree_element_active_ebone(
}
static eOLDrawState tree_element_active_modifier(
- bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
@@ -632,7 +633,7 @@ static eOLDrawState tree_element_active_psys(
}
static int tree_element_active_constraint(
- bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
@@ -645,7 +646,7 @@ static int tree_element_active_constraint(
}
static eOLDrawState tree_element_active_text(
- bContext *UNUSED(C), Scene *UNUSED(scene), SpaceOops *UNUSED(soops),
+ bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
TreeElement *UNUSED(te), int UNUSED(set))
{
// XXX removed
@@ -653,10 +654,10 @@ static eOLDrawState tree_element_active_text(
}
static eOLDrawState tree_element_active_pose(
- bContext *C, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *scene, SceneLayer *sl, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob = (Object *)tselem->id;
- Base *base = BKE_scene_base_find(scene, ob);
+ Base *base = BKE_scene_layer_base_find(sl, ob);
if (set != OL_SETSEL_NONE) {
if (scene->obedit)
@@ -737,7 +738,7 @@ static eOLDrawState tree_element_active_sequence_dup(
}
static eOLDrawState tree_element_active_keymap_item(
- bContext *UNUSED(C), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
+ bContext *UNUSED(C), Scene *UNUSED(scene), SceneLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
{
wmKeyMapItem *kmi = te->directdata;
@@ -753,10 +754,28 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
+static eOLDrawState tree_element_active_collection(
+ bContext *C, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
+{
+ if (set != OL_SETSEL_NONE) {
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *slayer = BLI_findlink(&scene->render_layers, scene->active_layer);
+ LayerCollection *collection = te->directdata;
+ const int collection_index = BKE_layer_collection_findindex(slayer, collection);
+
+ BLI_assert(collection_index >= 0);
+ slayer->active_collection = collection_index;
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OL_DRAWSEL_ACTIVE;
+ }
+
+ return OL_DRAWSEL_NONE;
+}
+
/* ---------------------------------------------- */
/* generic call for ID data check or make/check active in UI */
-eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te,
+eOLDrawState tree_element_active(bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops, TreeElement *te,
const eOLSetState set, const bool handle_all_types)
{
switch (te->idcode) {
@@ -764,21 +783,21 @@ eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, Tr
* selection. See do_outliner_item_activate. */
case ID_OB:
if (handle_all_types) {
- return tree_element_set_active_object(C, scene, soops, te, set, false);
+ return tree_element_set_active_object(C, scene, sl, soops, te, set, false);
}
break;
case ID_MA:
- return tree_element_active_material(C, scene, soops, te, set);
+ return tree_element_active_material(C, scene, sl, soops, te, set);
case ID_WO:
- return tree_element_active_world(C, scene, soops, te, set);
+ return tree_element_active_world(C, scene, sl, soops, te, set);
case ID_LA:
- return tree_element_active_lamp(C, scene, soops, te, set);
+ return tree_element_active_lamp(C, scene, sl, soops, te, set);
case ID_TE:
- return tree_element_active_texture(C, scene, soops, te, set);
+ return tree_element_active_texture(C, scene, sl, soops, te, set);
case ID_TXT:
- return tree_element_active_text(C, scene, soops, te, set);
+ return tree_element_active_text(C, scene, sl, soops, te, set);
case ID_CA:
- return tree_element_active_camera(C, scene, soops, te, set);
+ return tree_element_active_camera(C, scene, sl, soops, te, set);
}
return OL_DRAWSEL_NONE;
}
@@ -789,48 +808,49 @@ eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, Tr
* \note Context can be NULL when ``(set == OL_SETSEL_NONE)``
*/
eOLDrawState tree_element_type_active(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops,
TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
{
switch (tselem->type) {
case TSE_DEFGROUP:
- return tree_element_active_defgroup(C, scene, te, tselem, set);
+ return tree_element_active_defgroup(C, sl, te, tselem, set);
case TSE_BONE:
- return tree_element_active_bone(C, scene, te, tselem, set, recursive);
+ return tree_element_active_bone(C, sl, te, tselem, set, recursive);
case TSE_EBONE:
return tree_element_active_ebone(C, scene, te, tselem, set, recursive);
case TSE_MODIFIER:
- return tree_element_active_modifier(C, te, tselem, set);
+ return tree_element_active_modifier(C, scene, sl, te, tselem, set);
case TSE_LINKED_OB:
if (set != OL_SETSEL_NONE) {
- tree_element_set_active_object(C, scene, soops, te, set, false);
+ tree_element_set_active_object(C, scene, sl, soops, te, set, false);
}
- else if (tselem->id == (ID *)OBACT) {
+ else if (tselem->id == (ID *)OBACT_NEW) {
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);
+ return tree_element_active_pose(C, scene, sl, te, tselem, set);
case TSE_POSE_CHANNEL:
- return tree_element_active_posechannel(C, scene, te, tselem, set, recursive);
+ return tree_element_active_posechannel(C, scene, sl, te, tselem, set, recursive);
case TSE_CONSTRAINT:
- return tree_element_active_constraint(C, te, tselem, set);
+ return tree_element_active_constraint(C, scene, sl, te, tselem, set);
case TSE_R_LAYER:
- return tree_element_active_renderlayer(C, te, tselem, set);
+ return tree_element_active_renderlayer(C, scene, sl, te, tselem, set);
case TSE_POSEGRP:
- return tree_element_active_posegroup(C, scene, te, tselem, set);
+ return tree_element_active_posegroup(C, scene, sl, te, tselem, set);
case TSE_SEQUENCE:
return tree_element_active_sequence(C, scene, te, tselem, set);
case TSE_SEQUENCE_DUP:
return tree_element_active_sequence_dup(scene, te, tselem, set);
case TSE_KEYMAP_ITEM:
- return tree_element_active_keymap_item(C, te, tselem, set);
+ return tree_element_active_keymap_item(C, scene, sl, te, tselem, set);
case TSE_GP_LAYER:
- //return tree_element_active_gplayer(C, scene, te, tselem, set);
+ //return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
-
+ case TSE_COLLECTION:
+ return tree_element_active_collection(C, te, tselem, set);
}
return OL_DRAWSEL_NONE;
}
@@ -842,13 +862,14 @@ static void outliner_item_activate(
const bool extend, const bool recursive)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(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,
+ if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_COLLECTION)) {
+ tree_element_set_active_object(C, scene, sl, soops, te,
(extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
recursive && tselem->type == 0);
}
@@ -874,15 +895,17 @@ static void outliner_item_activate(
}
for (gob = gr->gobject.first; gob; gob = gob->next) {
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
+ ED_object_base_select(BKE_scene_layer_base_find(sl, gob->ob), sel);
}
}
else {
- BKE_scene_base_deselect_all(scene);
+ BKE_scene_layer_base_deselect_all(sl);
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);
+ Base *base = BKE_scene_layer_base_find(sl, gob->ob);
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ }
}
}
@@ -892,12 +915,12 @@ static void outliner_item_activate(
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);
+ tree_element_active(C, scene, sl, soops, te, OL_SETSEL_NORMAL, false);
}
}
else {
- tree_element_type_active(C, scene, soops, te, tselem,
+ tree_element_type_active(C, scene, sl, soops, te, tselem,
extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
recursive);
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 4560b7cd6e7..550dc63dd3c 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -56,6 +56,7 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -360,15 +361,15 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot)
/* ******************************************** */
static void object_select_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te,
+ bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Base *base = (Base *)te->directdata;
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base && ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) {
- base->flag |= SELECT;
- base->object->flag |= SELECT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+
+ if (base && ((base->flag & BASE_VISIBLED) != 0)) {
+ base->flag |= BASE_SELECTED;
}
}
@@ -385,46 +386,43 @@ static void object_select_hierarchy_cb(
static void object_deselect_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te,
+ bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Base *base = (Base *)te->directdata;
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+
if (base) {
- base->flag &= ~SELECT;
- base->object->flag &= ~SELECT;
+ base->flag &= ~BASE_SELECTED;
}
}
static void object_delete_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
+ bContext *C, ReportList *reports, Scene *scene, TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Base *base = (Base *)te->directdata;
-
- if (base == NULL)
- base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base) {
+ Object *ob = (Object *)tselem->id;
+ if (ob) {
Main *bmain = CTX_data_main(C);
- if (base->object->id.tag & LIB_TAG_INDIRECT) {
- BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
+ if (ob->id.tag & LIB_TAG_INDIRECT) {
+ BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
return;
}
- else if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
- ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0)
+ else if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
+ ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
{
BKE_reportf(reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- base->object->id.name + 2, scene->id.name + 2);
+ ob->id.name + 2, scene->id.name + 2);
return;
}
// check also library later
- if (scene->obedit == base->object)
+ if (scene->obedit == ob)
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
- ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
+ ED_base_object_free_and_unlink(CTX_data_main(C), scene, ob);
/* leave for ED_outliner_id_unref to handle */
#if 0
te->directdata = NULL;
@@ -520,7 +518,7 @@ static void group_linkobs2scene_cb(
{
Group *group = (Group *)tselem->id;
GroupObject *gob;
- Base *base;
+ BaseLegacy *base;
for (gob = group->gobject.first; gob; gob = gob->next) {
base = BKE_scene_base_find(scene, gob->ob);
@@ -530,7 +528,7 @@ static void group_linkobs2scene_cb(
id_us_plus(&gob->ob->id);
}
base->object->flag |= SELECT;
- base->flag |= SELECT;
+ base->flag_legacy |= SELECT;
}
}
@@ -820,9 +818,9 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li
}
}
-static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, Base *base)
+static BaseLegacy *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, BaseLegacy *base)
{
- Base *child_base, *base_next;
+ BaseLegacy *child_base, *base_next;
Object *parent;
if (!base) {
@@ -852,7 +850,7 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s
base->object->id.name + 2, scene->id.name + 2);
return base_next;
}
- ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
+ ED_base_object_free_and_unlink(CTX_data_main(C), scene, base->object);
return base_next;
}
@@ -860,6 +858,7 @@ static void object_delete_hierarchy_cb(
bContext *C, ReportList *reports, Scene *scene,
TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
+#if 0
Base *base = (Base *)te->directdata;
Object *obedit = scene->obedit;
@@ -882,6 +881,15 @@ static void object_delete_hierarchy_cb(
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+#else
+ (void) C;
+ (void) scene;
+ (void) te;
+ (void) tselem;
+ (void) outline_delete_hierarchy;
+ BKE_reportf(reports, RPT_ERROR, "Delete from outliner not supported at the moment");
+ TODO_LAYER_BASE
+#endif
}
/* **************************************** */
@@ -985,21 +993,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb);
str = "Localized Objects";
}
- else if (event == OL_OP_TOGVIS) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb);
- str = "Toggle Visibility";
- WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
- }
- else if (event == OL_OP_TOGSEL) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb);
- str = "Toggle Selectability";
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (event == OL_OP_TOGREN) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb);
- str = "Toggle Renderability";
- WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene);
- }
else if (event == OL_OP_RENAME) {
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb);
str = "Rename Object";
@@ -1095,15 +1088,6 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op)
case OL_GROUPOP_REMAP:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
break;
- case OL_GROUPOP_TOGVIS:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_visibility_cb, NULL);
- break;
- case OL_GROUPOP_TOGSEL:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_selectability_cb, NULL);
- break;
- case OL_GROUPOP_TOGREN:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_renderability_cb, NULL);
- break;
case OL_GROUPOP_RENAME:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
break;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ec46c5df9a0..c96d7f970ed 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -63,6 +63,7 @@
#include "BKE_fcurve.h"
#include "BKE_main.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
@@ -903,8 +904,8 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
id = TREESTORE(parent)->id;
}
- /* One exception */
- if (type == TSE_ID_BASE) {
+ /* exceptions */
+ if (ELEM(type, TSE_ID_BASE, TSE_COLLECTION)) {
/* pass */
}
else if (id == NULL) {
@@ -941,6 +942,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
+ else if (type == TSE_COLLECTION) {
+ /* pass */
+ }
else if (type == TSE_ID_BASE) {
/* pass */
}
@@ -1370,6 +1374,24 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
}
+static void outliner_add_collections_recursive(SpaceOops *soops, ListBase *tree, ListBase *layer_collections,
+ TreeElement *parent_ten)
+{
+ for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
+ TreeElement *ten = outliner_add_element(soops, tree, NULL, parent_ten, TSE_COLLECTION, 0);
+
+ ten->name = collection->scene_collection->name;
+ ten->directdata = collection;
+
+ outliner_add_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten);
+ }
+}
+
+static void outliner_add_collections(SpaceOops *soops, SceneLayer *layer)
+{
+ outliner_add_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL);
+}
+
/* ======================================================= */
/* Generic Tree Building helpers - order these are called is top to bottom */
@@ -1619,9 +1641,8 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
/* Main entry point for building the tree data-structure that the outliner represents */
// TODO: split each mode into its own function?
-void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
+void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops *soops)
{
- Base *base;
TreeElement *te = NULL, *ten;
TreeStoreElem *tselem;
int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */
@@ -1702,31 +1723,43 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
tselem = TREESTORE(te);
if (sce == scene && show_opened)
tselem->flag &= ~TSE_CLOSED;
-
- for (base = sce->base.first; base; base = base->next) {
- ten = outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
- ten->directdata = base;
+
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ ten = outliner_add_element(soops, &te->subtree, ob, te, 0, 0);
}
+ FOREACH_SCENE_OBJECT_END
+
outliner_make_hierarchy(&te->subtree);
+
/* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
- for (base = sce->base.first; base; base = base->next) base->object->id.newid = NULL;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ ob->id.newid = NULL;
+ }
+ FOREACH_SCENE_OBJECT_END
}
}
else if (soops->outlinevis == SO_CUR_SCENE) {
outliner_add_scene_contents(soops, &soops->tree, scene, NULL);
-
- for (base = scene->base.first; base; base = base->next) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
+
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
+ FOREACH_SCENE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_VISIBLE) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & scene->lay)
- outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ Object *ob;
+ FOREACH_VISIBLE_OBJECT(sl, ob)
+ {
+ outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
+ FOREACH_VISIBLE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_GROUPS) {
@@ -1739,7 +1772,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
for (go = group->gobject.first; go; go = go->next) {
ten = outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
- ten->directdata = NULL; /* eh, why? */
}
outliner_make_hierarchy(&te->subtree);
/* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
@@ -1748,26 +1780,26 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
}
}
else if (soops->outlinevis == SO_SAME_TYPE) {
- Object *ob = OBACT;
- if (ob) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->type == ob->type) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
+ Object *ob_active = OBACT_NEW;
+ if (ob_active) {
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ if (ob->type == ob_active->type) {
+ ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
}
+ FOREACH_SCENE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
}
else if (soops->outlinevis == SO_SELECTED) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & scene->lay) {
- if (base->flag & SELECT) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
- }
- }
+ Object *ob;
+ FOREACH_SELECTED_OBJECT(sl, ob)
+ {
+ ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
+ FOREACH_SELECTED_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_SEQUENCE) {
@@ -1821,9 +1853,11 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
+ else if (soops->outlinevis == SO_COLLECTIONS) {
+ outliner_add_collections(soops, BLI_findlink(&scene->render_layers, scene->active_layer));
+ }
else {
- ten = outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
- if (ten) ten->directdata = BASACT;
+ ten = outliner_add_element(soops, &soops->tree, OBACT_NEW, NULL, 0, 0);
}
if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index d7771d06787..b4cc1123176 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -758,6 +758,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
View2D *v2d = &ar->v2d;
float x1, x2, y1, y2;
unsigned char col[3], background_col[3], is_single_image;
+ float fcol[4] = {1.0f, 1.0f, 1.0f, 1.0f};
const float handsize_clamped = draw_seq_handle_size_get_clamped(seq, pixelx);
/* we need to know if this is a single image/color or not for drawing */
@@ -855,11 +856,11 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
glEnable(GL_LINE_STIPPLE);
glLineStipple(1, 0x8888);
}
-
- glColor3ubv((GLubyte *)col);
-
- UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
-
+
+ rgb_uchar_to_float(fcol, col);
+
+ UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0, fcol);
+
if (seq->flag & SEQ_MUTE) {
glDisable(GL_LINE_STIPPLE);
}
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 5e7060d6651..e9306c04cfa 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -402,7 +402,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN;
}
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index f0e65f84205..505ed1fdd3a 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -51,6 +51,8 @@
#include "BIF_gl.h"
+#include "GPU_immediate.h"
+
#include "ED_keyframes_draw.h"
@@ -86,10 +88,11 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar)
* - User selected color for next frames
*/
static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short sel, int sfra, int efra,
- float prev_color[3], float frame_color[3], float next_color[3])
+ float prev_color[3], float frame_color[3], float next_color[3], unsigned color)
{
int frame = sfra + i;
int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
+ unsigned char ubcolor[3];
#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
float intensity; /* how faint */
@@ -97,7 +100,7 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short
if (frame < CFRA) {
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
/* Custom color: previous frames color is darker than current frame */
- glColor3fv(prev_color);
+ rgb_float_to_uchar(ubcolor, prev_color);
}
else {
/* black - before cfra */
@@ -109,13 +112,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short
/* intensity = 0.8f; */
intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
}
- UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
+
+ UI_GetThemeColorBlend3ubv(TH_WIRE, blend_base, intensity, ubcolor);
}
}
else if (frame > CFRA) {
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
/* Custom color: next frames color is equal to user selected color */
- glColor3fv(next_color);
+ rgb_float_to_uchar(ubcolor, next_color);
}
else {
/* blue - after cfra */
@@ -127,13 +131,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short
/* intensity = 0.8f; */
intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
}
- UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
+
+ UI_GetThemeColorBlend3ubv(TH_BONE_POSE, blend_base, intensity, ubcolor);
}
}
else {
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
/* Custom color: current frame color is slightly darker than user selected color */
- glColor3fv(frame_color);
+ rgb_float_to_uchar(ubcolor, frame_color);
}
else {
/* green - on cfra */
@@ -143,9 +148,12 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short
else {
intensity = 0.99f;
}
- UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
+ UI_GetThemeColorBlendShade3ubv(TH_CFRAME, TH_BACK, intensity, 10, ubcolor);
}
}
+
+ immAttrib3ubv(color, ubcolor);
+
#undef SET_INTENSITY
}
@@ -231,42 +239,65 @@ void draw_motion_path_instance(Scene *scene,
/* set line thickness */
glLineWidth(mpath->line_thickness);
- glBegin(GL_LINE_STRIP);
+ 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_SMOOTH_COLOR);
+
+ immBegin(GL_LINE_STRIP, len);
+
for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
+
/* Set color */
- set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color);
+ set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color, color);
+
/* draw a vertex with this color */
- glVertex3fv(mpv->co);
+ immVertex3fv(pos, mpv->co);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
+
/* back to old line thickness */
glLineWidth(old_width);
}
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
/* Point must be bigger than line thickness */
glPointSize(mpath->line_thickness + 1.0);
- /* draw little black point at each frame
- * NOTE: this is not really visible/noticeable
- */
- glBegin(GL_POINTS);
- for (i = 0, mpv = mpv_start; i < len; i++, mpv++)
- glVertex3fv(mpv->co);
- glEnd();
-
+ /* draw little black point at each frame */
+ immUniformColor3ub(0, 0, 0);
+
+ immBegin(GL_POINTS, len);
+
+ for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
+ immVertex3fv(pos, mpv->co);
+ }
+
+ immEnd();
+
/* Draw little white dots at each framestep value or replace with custom color */
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
- glColor4fv(mpath->color);
+ immUniformColor3fv(mpath->color);
}
else {
- UI_ThemeColor(TH_TEXT_HI);
+ immUniformThemeColor(TH_TEXT_HI);
}
- glBegin(GL_POINTS);
- for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize)
- glVertex3fv(mpv->co);
- glEnd();
+
+ immBegin(GL_POINTS, (len + stepsize - 1) / stepsize);
+
+ for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
+ immVertex3fv(pos, mpv->co);
+ }
+
+ immEnd();
/* Draw big green dot where the current frame is
* NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
@@ -274,16 +305,18 @@ void draw_motion_path_instance(Scene *scene,
if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) &&
(sfra < CFRA) && (CFRA <= efra))
{
- UI_ThemeColor(TH_CFRAME);
-
glPointSize(mpath->line_thickness + 5.0);
- glBegin(GL_POINTS);
+ immUniformThemeColor(TH_CFRAME);
+
+ immBegin(GL_POINTS, 1);
+
mpv = mpv_start + (CFRA - sfra);
- glVertex3fv(mpv->co);
- glEnd();
-
- UI_ThemeColor(TH_TEXT_HI);
+ immVertex3fv(pos, mpv->co);
+
+ immEnd();
}
+
+ immUnbindProgram();
/* XXX, this isn't up to date but probably should be kept so. */
invert_m4_m4(ob->imat, ob->obmat);
@@ -353,24 +386,28 @@ void draw_motion_path_instance(Scene *scene,
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
col[3] = 255;
- /* if custom, point must be bigger than line */
- if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
- glPointSize(mpath->line_thickness + 3.0);
- }
- else {
- glPointSize(4.0f);
- }
- glColor3ubv(col);
+ /* point must be bigger than line */
+ glPointSize(mpath->line_thickness + 3.0);
+
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(col);
- glBegin(GL_POINTS);
+ immBeginAtMost(GL_POINTS, len);
+
for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
int frame = sfra + i;
float mframe = (float)(frame);
- if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe))
- glVertex3fv(mpv->co);
+ if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
+ immVertex3fv(pos, mpv->co);
+ }
}
- glEnd();
+
+ immEnd();
+
+ immUnbindProgram();
/* Draw frame numbers of keyframes */
if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) {
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index af041e392c5..a7bff0a8301 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -63,6 +63,8 @@
#include "ED_keyframes_draw.h"
#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
+#include "GPU_matrix.h"
#include "UI_resources.h"
@@ -74,6 +76,7 @@
/* global here is reset before drawing each bone */
static ThemeWireColor *bcolor = NULL;
+static float fcolor[4] = {0.0f};
/* values of colCode for set_pchan_glcolor */
enum {
@@ -148,11 +151,12 @@ static void cp_shade_color3ub(unsigned char cp[3], const int offset)
/* This function sets the gl-color for coloring a certain bone (based on bcolor) */
static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
{
+ /* TODO remove glColor/UI_ThemeColor functions when no longer needed */
switch (colCode) {
case PCHAN_COLOR_NORMAL:
{
if (bcolor) {
- unsigned char cp[3];
+ unsigned char cp[4] = {255};
if (boneflag & BONE_DRAW_ACTIVE) {
copy_v3_v3_char((char *)cp, bcolor->active);
@@ -170,19 +174,24 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
}
glColor3ubv(cp);
+ rgb_uchar_to_float(fcolor, cp);
}
else {
if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
UI_ThemeColor(TH_BONE_POSE_ACTIVE);
+ UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor);
}
else if (boneflag & BONE_DRAW_ACTIVE) {
UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */
+ UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor);
}
else if (boneflag & BONE_SELECTED) {
UI_ThemeColor(TH_BONE_POSE);
+ UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
}
else {
UI_ThemeColor(TH_WIRE);
+ UI_GetThemeColor4fv(TH_WIRE, fcolor);
}
}
@@ -192,20 +201,27 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
{
if (bcolor) {
glColor3ubv((unsigned char *)bcolor->solid);
+ rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid);
}
- else
+ else {
UI_ThemeColor(TH_BONE_SOLID);
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
return true;
}
case PCHAN_COLOR_CONSTS:
{
if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) {
- if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80);
- else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
- else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80);
- else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
-
+ unsigned char cp[4];
+ if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80);
+ else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80);
+ else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80);
+ else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80);
+
+ glColor4ubv(cp);
+ rgba_uchar_to_float(fcolor, cp);
+
return true;
}
return false;
@@ -213,7 +229,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
case PCHAN_COLOR_SPHEREBONE_BASE:
{
if (bcolor) {
- unsigned char cp[3];
+ unsigned char cp[4] = {255};
if (boneflag & BONE_DRAW_ACTIVE) {
copy_v3_v3_char((char *)cp, bcolor->active);
@@ -226,11 +242,21 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
}
glColor3ubv(cp);
+ rgb_uchar_to_float(fcolor, cp);
}
else {
- if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40);
- else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
- else UI_ThemeColor(TH_BONE_SOLID);
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ UI_ThemeColorShade(TH_BONE_POSE, 40);
+ UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ UI_ThemeColor(TH_BONE_POSE);
+ UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
+ }
+ else {
+ UI_ThemeColor(TH_BONE_SOLID);
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
}
return true;
@@ -238,7 +264,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
case PCHAN_COLOR_SPHEREBONE_END:
{
if (bcolor) {
- unsigned char cp[3];
+ unsigned char cp[4] = {255};
if (boneflag & BONE_DRAW_ACTIVE) {
copy_v3_v3_char((char *)cp, bcolor->active);
@@ -254,11 +280,21 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
}
glColor3ubv(cp);
+ rgb_uchar_to_float(fcolor, cp);
}
else {
- if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10);
- else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30);
- else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ UI_ThemeColorShade(TH_BONE_POSE, 10);
+ UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ UI_ThemeColorShade(TH_BONE_POSE, -30);
+ UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor);
+ }
+ else {
+ UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
+ }
}
break;
}
@@ -266,19 +302,27 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
{
/* inner part in background color or constraint */
if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) {
- if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0);
- else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0);
- else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0);
- else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120);
- else if (constflag) UI_ThemeColor(TH_BONE_POSE); /* PCHAN_HAS_ACTION */
+ unsigned char cp[4];
+ if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255);
+ else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255);
+ else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255);
+ else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255);
+ else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp); /* PCHAN_HAS_ACTION */
+
+ glColor4ubv(cp);
+ rgb_uchar_to_float(fcolor, cp);
}
else {
if (bcolor) {
const char *cp = bcolor->solid;
glColor4ub(cp[0], cp[1], cp[2], 204);
+ rgb_uchar_to_float(fcolor, (unsigned char *)cp);
+ fcolor[3] = 204.f / 255.f;
}
- else
+ else {
UI_ThemeColorShade(TH_BACK, -30);
+ UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
+ }
}
return true;
@@ -290,24 +334,29 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
static void set_ebone_glColor(const unsigned int boneflag)
{
+ /* TODO remove glColor/UI_ThemeColor functions when no longer needed */
if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
UI_ThemeColor(TH_EDGE_SELECT);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor);
}
else if (boneflag & BONE_DRAW_ACTIVE) {
UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f); /* unselected active */
+ UI_GetThemeColorBlendShade4fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, fcolor);
}
else if (boneflag & BONE_SELECTED) {
UI_ThemeColorShade(TH_EDGE_SELECT, -20);
+ UI_GetThemeColorShade4fv(TH_EDGE_SELECT, -20, fcolor);
}
else {
UI_ThemeColor(TH_WIRE_EDIT);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
}
}
/* *************** Armature drawing, helper calls for parts ******************* */
/* half the cube, in Y */
-static const float cube[8][3] = {
+static const float cube_vert[8][3] = {
{-1.0, 0.0, -1.0},
{-1.0, 0.0, 1.0},
{-1.0, 1.0, 1.0},
@@ -318,6 +367,12 @@ static const float cube[8][3] = {
{ 1.0, 1.0, -1.0},
};
+static const float cube_wire[24] = {
+ 0, 1, 1, 2, 2, 3, 3, 0,
+ 4, 5, 5, 6, 6, 7, 7, 4,
+ 0, 4, 1, 5, 2, 6, 3, 7,
+};
+
static void drawsolidcube_size(float xsize, float ysize, float zsize)
{
static GLuint displist = 0;
@@ -332,26 +387,26 @@ static void drawsolidcube_size(float xsize, float ysize, float zsize)
glBegin(GL_QUADS);
n[0] = -1.0;
glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+ glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[1]); glVertex3fv(cube_vert[2]); glVertex3fv(cube_vert[3]);
n[0] = 0;
n[1] = -1.0;
glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
+ glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[5]); glVertex3fv(cube_vert[1]);
n[1] = 0;
n[0] = 1.0;
glNormal3fv(n);
- glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
+ glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[6]); glVertex3fv(cube_vert[5]);
n[0] = 0;
n[1] = 1.0;
glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+ glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[3]); glVertex3fv(cube_vert[2]); glVertex3fv(cube_vert[6]);
n[1] = 0;
n[2] = 1.0;
glNormal3fv(n);
- glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
+ glVertex3fv(cube_vert[1]); glVertex3fv(cube_vert[5]); glVertex3fv(cube_vert[6]); glVertex3fv(cube_vert[2]);
n[2] = -1.0;
glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
+ glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[3]);
glEnd();
glEndList();
@@ -362,30 +417,42 @@ static void drawsolidcube_size(float xsize, float ysize, float zsize)
static void drawcube_size(float xsize, float ysize, float zsize)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- glBegin(GL_LINE_STRIP);
- glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
- glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
- glVertex3fv(cube[7]); glVertex3fv(cube[4]);
- glEnd();
-
- glBegin(GL_LINES);
- glVertex3fv(cube[1]); glVertex3fv(cube[5]);
- glVertex3fv(cube[2]); glVertex3fv(cube[6]);
- glVertex3fv(cube[3]); glVertex3fv(cube[7]);
- glEnd();
-
- glEndList();
+ static VertexFormat format = {0};
+ static VertexBuffer vbo = {0};
+ static ElementListBuilder elb = {0};
+ static ElementList el = {0};
+ static Batch batch = {0};
+
+ if (format.attrib_ct == 0) {
+ /* Vertex format */
+ unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ /* Elements */
+ ElementListBuilder_init(&elb, GL_LINES, 12, 8);
+ for (int i = 0; i < 12; ++i) {
+ add_line_vertices(&elb, cube_wire[i*2], cube_wire[i*2+1]);
+ }
+ ElementList_build_in_place(&elb, &el);
+
+ /* Vertices */
+ VertexBuffer_init_with_format(&vbo, &format);
+ VertexBuffer_allocate_data(&vbo, 8);
+ for (int i = 0; i < 8; ++i) {
+ setAttrib(&vbo, pos, i, cube_vert[i]);
+ }
+
+ Batch_init(&batch, GL_LINES, &vbo, &el);
+ Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- glScalef(xsize, ysize, zsize);
- glCallList(displist);
-
+ gpuMatrixBegin3D_legacy();
+ gpuScale3f(xsize, ysize, zsize);
+
+ Batch_use_program(&batch);
+ Batch_Uniform4fv(&batch, "color", fcolor);
+ Batch_draw(&batch);
+
+ gpuMatrixEnd();
}
@@ -451,8 +518,11 @@ static const float bone_octahedral_verts[6][3] = {
{ 0.0f, 1.0f, 0.0f}
};
-static const unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2};
-static const unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1};
+static const unsigned int bone_octahedral_wire[24] = {
+ 0, 1, 1, 5, 5, 3, 3, 0,
+ 0, 4, 4, 5, 5, 2, 2, 0,
+ 1, 2, 2, 3, 3, 4, 4, 1,
+};
static const unsigned int bone_octahedral_solid_tris[8][3] = {
{2, 1, 0}, /* bottom */
@@ -480,31 +550,41 @@ static const float bone_octahedral_solid_normals[8][3] = {
static void draw_bone_octahedral(void)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
+ static VertexFormat format = {0};
+ static VertexBuffer vbo = {0};
+ static ElementListBuilder elb = {0};
+ static ElementList el = {0};
+ static Batch batch = {0};
+
+ if (format.attrib_ct == 0) {
+ /* Vertex format */
+ unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ /* Elements */
+ ElementListBuilder_init(&elb, GL_LINES, 12, 6);
+ for (int i = 0; i < 12; ++i) {
+ add_line_vertices(&elb, bone_octahedral_wire[i*2], bone_octahedral_wire[i*2+1]);
+ }
+ ElementList_build_in_place(&elb, &el);
- /* Section 1, sides */
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts);
- glDrawElements(GL_LINE_LOOP,
- sizeof(bone_octahedral_wire_sides) / sizeof(*bone_octahedral_wire_sides),
- GL_UNSIGNED_INT,
- bone_octahedral_wire_sides);
-
- /* Section 1, square */
- glDrawElements(GL_LINE_LOOP,
- sizeof(bone_octahedral_wire_square) / sizeof(*bone_octahedral_wire_square),
- GL_UNSIGNED_INT,
- bone_octahedral_wire_square);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glEndList();
+ /* Vertices */
+ VertexBuffer_init_with_format(&vbo, &format);
+ VertexBuffer_allocate_data(&vbo, 6);
+ for (int i = 0; i < 6; ++i) {
+ setAttrib(&vbo, pos, i, bone_octahedral_verts[i]);
+ }
+
+ Batch_init(&batch, GL_LINES, &vbo, &el);
+ Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- glCallList(displist);
+ gpuMatrixBegin3D_legacy();
+
+ Batch_use_program(&batch);
+ Batch_Uniform4fv(&batch, "color", fcolor);
+ Batch_draw(&batch);
+
+ gpuMatrixEnd();
}
static void draw_bone_solid_octahedral(void)
@@ -1733,7 +1813,7 @@ static void bone_matrix_translate_y(float mat[4][4], float y)
}
/* assumes object is Armature with pose */
-static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
+static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base,
const short dt, const unsigned char ob_wire_col[4],
const bool do_const_color, const bool is_outline)
{
@@ -1753,6 +1833,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
bool draw_wire = false;
int flag;
bool is_cull_enabled;
+
+ /* TODO find a way to overcome this.
+ * used in case do_const_color is true */
+ glGetFloatv(GL_CURRENT_COLOR, fcolor);
/* being set below */
arm->layer_used = 0;
@@ -1938,6 +2022,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
set_pchan_colorset(ob, pchan);
else {
glColor3ubv(ob_wire_col);
+ rgba_uchar_to_float(fcolor, ob_wire_col);
}
/* catch exception for bone with hidden parent */
@@ -2106,7 +2191,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* draw DoFs */
if (arm->flag & ARM_POSEMODE) {
- if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) {
+ if (((base->flag_legacy & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) {
draw_pose_dofs(ob);
}
}
@@ -2114,7 +2199,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* finally names and axes */
if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) &&
(is_outline == 0) &&
- ((base->flag & OB_FROMDUPLI) == 0))
+ ((base->flag_legacy & OB_FROMDUPLI) == 0))
{
/* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */
if ((G.f & G_PICKSEL) == 0) {
@@ -2445,7 +2530,7 @@ static void ghost_poses_tag_unselected(Object *ob, short unset)
/* draw ghosts that occur within a frame range
* note: object should be in posemode
*/
-static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
+static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2511,7 +2596,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
/* draw ghosts on keyframes in action within range
* - object should be in posemode
*/
-static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
+static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2592,7 +2677,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *
/* draw ghosts around current frame
* - object is supposed to be armature in posemode
*/
-static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
+static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2686,7 +2771,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
/* called from drawobject.c, return true if nothing was drawn
* (ob_wire_col == NULL) when drawing ghost */
-bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
+bool draw_armature(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
const short dt, const short dflag, const unsigned char ob_wire_col[4],
const bool is_outline)
{
@@ -2733,7 +2818,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
/* drawing posemode selection indices or colors only in these cases */
- if (!(base->flag & OB_FROMDUPLI)) {
+ if (!(base->flag_legacy & OB_FROMDUPLI)) {
if (G.f & G_PICKSEL) {
#if 0
/* nifty but actually confusing to allow bone selection out of posemode */
@@ -2759,10 +2844,10 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
draw_ghost_poses(scene, v3d, ar, base);
}
if ((dflag & DRAW_SCENESET) == 0) {
- if (ob == OBACT)
+ if (ob == OBACT_NEW)
arm->flag |= ARM_POSEMODE;
- else if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
- if (ob == modifiers_isDeformedByArmature(OBACT))
+ else if (OBACT_NEW && (OBACT_NEW->mode & OB_MODE_WEIGHT_PAINT)) {
+ if (ob == modifiers_isDeformedByArmature(OBACT_NEW))
arm->flag |= ARM_POSEMODE;
}
draw_pose_paths(scene, v3d, ar, ob);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 1692d3a7372..5d821734b63 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -323,9 +323,9 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
return false;
}
-static bool check_alpha_pass(Base *base)
+static bool check_alpha_pass(BaseLegacy *base)
{
- if (base->flag & OB_FROMDUPLI)
+ if (base->flag_legacy & OB_FROMDUPLI)
return false;
if (G.f & G_PICKSEL)
@@ -787,7 +787,7 @@ void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][
glDisableClientState(GL_VERTEX_ARRAY);
}
-static void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos)
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos)
{
float verts[CIRCLE_RESOL][3];
@@ -1247,7 +1247,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
!(G.f & G_PICKSEL) &&
(la->type == LA_SPOT) &&
(la->mode & LA_SHOW_CONE) &&
- !(base->flag & OB_FROMDUPLI) &&
+ !(base->flag_legacy & OB_FROMDUPLI) &&
!is_view);
#ifdef WITH_GAMEENGINE
@@ -1259,7 +1259,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
((la->mode & LA_SHAD_BUF) ||
(la->mode & LA_SHAD_RAY)) &&
(la->mode & LA_SHOW_SHADOW_BOX) &&
- !(base->flag & OB_FROMDUPLI) &&
+ !(base->flag_legacy & OB_FROMDUPLI) &&
!is_view);
#else
const bool drawshadowbox = false;
@@ -1309,7 +1309,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
if ((dflag & DRAW_CONSTCOLOR) == 0) {
const float *color = curcol;
if (ob->id.us > 1) {
- if (is_obact || (ob->flag & SELECT)) {
+ if (is_obact || ((base->flag & BASE_SELECTED) != 0)) {
static const float active_color[4] = {0.533f, 1.0f, 1.0f, 1.0f};
color = active_color;
}
@@ -1690,7 +1690,7 @@ static void draw_bundle_sphere(void)
}
static void draw_viewport_object_reconstruction(
- Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d,
+ Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d,
MovieClip *clip, MovieTrackingObject *tracking_object,
const short dflag, const unsigned char ob_wire_col[4],
int *global_track_index, bool draw_selected)
@@ -1852,7 +1852,7 @@ static void draw_viewport_object_reconstruction(
}
static void draw_viewport_reconstruction(
- Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip,
+ Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip,
const short dflag, const unsigned char ob_wire_col[4],
const bool draw_selected)
{
@@ -4188,7 +4188,7 @@ static bool object_is_halo(Scene *scene, Object *ob)
return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene));
}
-static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
#ifdef WITH_GAMEENGINE
@@ -4254,7 +4254,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if ((v3d->flag & V3D_SELECT_OUTLINE) &&
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (base->flag & SELECT) &&
+ (base->flag & BASE_SELECTED) &&
!(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
(draw_wire == OBDRAW_WIRE_OFF))
{
@@ -4325,7 +4325,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
/* draw outline */
if ((v3d->flag & V3D_SELECT_OUTLINE) &&
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (base->flag & SELECT) &&
+ (base->flag & BASE_SELECTED) &&
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
@@ -4349,7 +4349,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if ((v3d->flag & V3D_SELECT_OUTLINE) &&
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (base->flag & SELECT) &&
+ (base->flag & BASE_SELECTED) &&
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
@@ -4451,7 +4451,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
/* returns true if nothing was drawn, for detecting to draw an object center */
-static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
@@ -4541,7 +4541,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
}
}
- if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
+ if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
/* GPU_begin_object_materials checked if this is needed */
if (do_alpha_after) {
if (ob->dtx & OB_DRAWXRAY) {
@@ -4595,7 +4595,7 @@ static void make_color_variations(const unsigned char base_ubyte[4], float low[4
high[3] = base[3];
}
-static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit)
{
if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
@@ -4731,7 +4731,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
if ((v3d->flag & V3D_SELECT_OUTLINE) &&
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (base->flag & SELECT) &&
+ (base->flag & BASE_SELECTED) &&
!(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
(draw_wire == OBDRAW_WIRE_OFF))
{
@@ -4798,7 +4798,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
/* TODO: move this into a separate pass */
if ((v3d->flag & V3D_SELECT_OUTLINE) &&
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (base->flag & SELECT) &&
+ (base->flag & BASE_SELECTED) &&
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
@@ -4822,7 +4822,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
if ((v3d->flag & V3D_SELECT_OUTLINE) &&
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (base->flag & SELECT) &&
+ (base->flag & BASE_SELECTED) &&
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
@@ -4914,7 +4914,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
dm->release(dm);
}
-static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
@@ -5253,7 +5253,7 @@ static void drawCurveDMWired(Object *ob)
}
/* return true when nothing was drawn */
-static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt)
+static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt)
{
Object *ob = base->object;
DerivedMesh *dm = ob->derivedFinal;
@@ -5289,7 +5289,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d,
* Only called by #drawDispList
* \return true when nothing was drawn
*/
-static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
@@ -5410,7 +5410,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
return false;
}
-static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
bool retval;
@@ -5697,7 +5697,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
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;
+ bool select = (base->flag & BASE_SELECTED) != 0, create_cdata = false, need_v = false;
GLint polygonmode[2];
char numstr[32];
unsigned char tcol[4] = {0, 0, 0, 255};
@@ -5768,7 +5768,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
timestep = psys_get_timestep(&sim);
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
+ if ((ob->flag & OB_FROMGROUP) != 0) {
float mat[4][4];
mul_m4_m4m4(mat, ob->obmat, psys->imat);
glMultMatrixf(mat);
@@ -6399,7 +6399,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pdd->ma_col = NULL;
}
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
+ if ((ob->flag & OB_FROMGROUP) != 0) {
glLoadMatrixf(rv3d->viewmat);
}
}
@@ -7059,7 +7059,7 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
}
static void draw_editnurb(
- Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
+ Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, Nurb *nurb,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
ToolSettings *ts = scene->toolsettings;
@@ -7169,7 +7169,7 @@ static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2])
ED_view3d_polygon_offset(rv3d, 0.0);
}
-static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
@@ -7527,7 +7527,7 @@ static void imm_drawcone(const float vec[3], float radius, float height, float t
}
/* return true if nothing was drawn */
-static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
@@ -7548,7 +7548,7 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
ml = mb->editelems->first;
}
else {
- if ((base->flag & OB_FROMDUPLI) == 0) {
+ if ((base->flag_legacy & OB_FROMDUPLI) == 0) {
drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
ml = mb->elems.first;
@@ -7942,7 +7942,7 @@ static void drawtexspace(Object *ob)
}
/* draws wire outline */
-static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
+static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
const unsigned char ob_wire_col[4])
{
RegionView3D *rv3d = ar->regiondata;
@@ -7982,16 +7982,16 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
- if ((base->flag & OB_FROMDUPLI) == 0) {
+ if ((base->flag_legacy & OB_FROMDUPLI) == 0) {
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
drawDispListwire(&ob->curve_cache->disp, ob->type);
}
}
}
else if (ob->type == OB_ARMATURE) {
- if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) {
+ if (!(ob->mode & OB_MODE_POSE && base == sl->basact)) {
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true);
+ draw_armature(scene, sl, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true);
}
}
@@ -8095,7 +8095,7 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
setlinestyle(0);
}
-void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4])
+void draw_object_wire_color(Scene *scene, SceneLayer *sl, Base *base, unsigned char r_ob_wire_col[4])
{
Object *ob = base->object;
int colindex = 0;
@@ -8109,19 +8109,19 @@ void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_co
if ((scene->obedit == NULL) &&
(G.moving & G_TRANSFORM_OBJ) &&
- (base->flag & (SELECT + BA_WAS_SEL)))
+ ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)))
{
theme_id = TH_TRANSFORM;
}
else {
/* Sets the 'colindex' */
if (ID_IS_LINKED_DATABLOCK(ob)) {
- colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 2 : 1;
+ colindex = ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) ? 2 : 1;
}
/* Sets the 'theme_id' or fallback to wire */
else {
- if (ob->flag & OB_FROMGROUP) {
- if (base->flag & (SELECT + BA_WAS_SEL)) {
+ if ((ob->flag & OB_FROMGROUP) != 0) {
+ if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) {
/* uses darker active color for non-active + selected */
theme_id = TH_GROUP_ACTIVE;
@@ -8134,8 +8134,8 @@ void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_co
}
}
else {
- if (base->flag & (SELECT + BA_WAS_SEL)) {
- theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT;
+ if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) {
+ theme_id = sl->basact == base ? TH_ACTIVE : TH_SELECT;
}
else {
if (ob->type == OB_LAMP) theme_id = TH_LAMP;
@@ -8233,7 +8233,7 @@ void draw_rigidbody_shape(Object *ob)
* main object drawing function, draws in selection
* \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET
*/
-void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag)
+void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base, const short dflag)
{
ModifierData *md = NULL;
Object *ob = base->object;
@@ -8243,7 +8243,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
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 is_obact = (ob == OBACT_NEW);
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);
@@ -8283,7 +8283,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- if (((base->flag & OB_FROMDUPLI) == 0) &&
+ if (((base->flag_legacy & OB_FROMDUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Smoke)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)))
{
@@ -8307,7 +8307,7 @@ 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) {
+ if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & 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)) {
/* xray and transp are set when it is drawing the 2nd/3rd pass */
@@ -8360,7 +8360,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
ED_view3d_project_base(ar, base);
- draw_object_wire_color(scene, base, _ob_wire_col);
+ draw_object_wire_color(scene, sl, base, _ob_wire_col);
ob_wire_col = _ob_wire_col;
glColor3ubv(ob_wire_col);
@@ -8415,8 +8415,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* 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) {
- if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) {
- drawObjectSelect(scene, v3d, ar, base, ob_wire_col);
+ if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) {
+ drawObjectSelect(scene, sl, v3d, ar, base, ob_wire_col);
}
}
}
@@ -8552,7 +8552,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
else {
glLineWidth(1.0f);
- empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false);
+ empty_object = draw_armature(scene, sl, v3d, ar, base, dt, dflag, ob_wire_col, false);
}
}
break;
@@ -8598,7 +8598,7 @@ afterdraw:
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* for visibility, also while wpaint */
- if (col || (ob->flag & SELECT)) {
+ if (col || (base->flag & BASE_SELECTED)) {
cpack(0xFFFFFF);
}
}
@@ -8805,7 +8805,7 @@ afterdraw:
glDisable(GL_DEPTH_TEST);
}
- if ((base->flag & OB_FROMDUPLI) || render_override) {
+ if ((base->flag_legacy & OB_FROMDUPLI) || render_override) {
ED_view3d_clear_mats_rv3d(rv3d);
return;
}
@@ -8819,7 +8819,7 @@ afterdraw:
}
else if (is_obact)
do_draw_center = ACTIVE;
- else if (base->flag & SELECT)
+ else if (base->flag & BASE_SELECTED)
do_draw_center = SELECT;
else if (empty_object || (v3d->flag & V3D_DRAW_CENTERS))
do_draw_center = DESELECT;
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 27ecbf83db5..debdcb58d71 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -160,7 +160,7 @@ static GPUTexture *create_field_texture(SmokeDomainSettings *sds)
default: return NULL;
}
- return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field);
+ return GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, GPU_R8, field, NULL);
}
typedef struct VolumeSlicer {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 9b65784f52b..046aa40b85d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -592,6 +592,7 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
if (rv3d->viewport) {
GPU_viewport_free(rv3d->viewport);
+ MEM_freeN(rv3d->viewport);
rv3d->viewport = NULL;
}
}
@@ -653,7 +654,7 @@ static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *eve
static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval);
/* either holding and ctrl and no object, or dropping to empty */
if (((base == NULL) && event->ctrl) ||
@@ -667,7 +668,7 @@ static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *
static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ BaseLegacy *base = ED_view3d_give_base_under_cursor(C, event->mval);
if (base && base->object->type == OB_MESH)
return view3d_ima_drop_poll(C, drag, event);
@@ -753,6 +754,7 @@ static void view3d_main_region_free(ARegion *ar)
}
if (rv3d->viewport) {
GPU_viewport_free(rv3d->viewport);
+ MEM_freeN(rv3d->viewport);
}
MEM_freeN(rv3d);
@@ -790,7 +792,7 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene
wmWindow *win = wmn->wm->winactive;
ScrArea *sa;
unsigned int lay_used = 0;
- Base *base;
+ BaseLegacy *base;
if (!win) return;
@@ -1287,8 +1289,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
}
const char *view3d_context_dir[] = {
- "selected_objects", "selected_bases", "selected_editable_objects",
- "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
"active_base", "active_object", NULL
};
@@ -1299,109 +1299,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, view3d_context_dir);
}
- else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool selected_objects = CTX_data_equals(member, "selected_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (selected_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (0 == BKE_object_is_libdata(base->object)) {
- if (selected_editable_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool visible_objects = CTX_data_equals(member, "visible_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & lay) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (visible_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool selectable_objects = CTX_data_equals(member, "selectable_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & lay) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
- if (selectable_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
else if (CTX_data_equals(member, "active_base")) {
- View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- if (scene->basact && (scene->basact->lay & lay)) {
- Object *ob = scene->basact->object;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ if (sl->basact) {
+ Object *ob = sl->basact->object;
/* if hidden but in edit mode, we still display, can happen with animation */
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
- CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact);
+ if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact);
+ }
}
return 1;
}
else if (CTX_data_equals(member, "active_object")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- if (scene->basact && (scene->basact->lay & lay)) {
- Object *ob = scene->basact->object;
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
- CTX_data_id_pointer_set(result, &scene->basact->object->id);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ if (sl->basact) {
+ Object *ob = sl->basact->object;
+ /* if hidden but in edit mode, we still display, can happen with animation */
+ if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ CTX_data_id_pointer_set(result, &ob->id);
+ }
}
return 1;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 17622d9dbb1..46ffde7f671 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -699,7 +699,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
/* camera name - draw in highlighted text color */
if (ca && (ca->flag & CAM_SHOWNAME)) {
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
BLF_draw_default(
x1i, y1i - (0.7f * U.widget_unit), 0.0f,
v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
@@ -1645,11 +1645,11 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
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_color4ubv(BLF_default(), axis_col[i]);
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 */
+ /* BLF_draw disabled blending for us */
}
#ifdef WITH_INPUT_NDOF
@@ -1768,7 +1768,7 @@ static void draw_rotation_guide(RegionView3D *rv3d)
/* ******************** non-meshes ***************** */
static void view3d_draw_non_mesh(
-Scene *scene, Object *ob, Base *base, View3D *v3d,
+Scene *scene, SceneLayer *sl, Object *ob, Base *base, View3D *v3d,
RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
{
glMatrixMode(GL_PROJECTION);
@@ -1794,7 +1794,7 @@ RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, color);
break;
case OB_LAMP:
- drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, ob == OBACT);
+ drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, ob == OBACT_NEW);
break;
case OB_CAMERA:
drawcamera(scene, v3d, rv3d, base, DRAW_CONSTCOLOR, color);
@@ -1873,6 +1873,7 @@ static void view3d_draw_setup_view(const bContext *C, ARegion *ar)
static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C);
if (only_depth)
@@ -1885,13 +1886,13 @@ static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_dep
v3d->zbuf = true;
}
- for (Base *base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
/* dupli drawing */
if (base->object->transflag & OB_DUPLI)
- draw_dupli_objects(scene, ar, v3d, base);
+ draw_dupli_objects(scene, sl, ar, v3d, base);
- draw_object(scene, ar, v3d, base, 0);
+ draw_object(scene, sl, ar, v3d, base, 0);
}
}
@@ -1969,6 +1970,7 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
* we filter them based on the plates/layers
*/
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
@@ -1982,13 +1984,13 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
* for now let's avoid writing again to zbuffer to prevent glitches
*/
- for (Base *base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
Object *ob = base->object;
unsigned char ob_wire_col[4];
- draw_object_wire_color(scene, base, ob_wire_col);
- view3d_draw_non_mesh(scene, ob, base, v3d, rv3d, is_boundingbox, ob_wire_col);
+ draw_object_wire_color(scene, sl, base, ob_wire_col);
+ view3d_draw_non_mesh(scene, sl, ob, base, v3d, rv3d, is_boundingbox, ob_wire_col);
}
}
@@ -2100,12 +2102,42 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data
#endif
}
+static void view3d_render_pass(const bContext *C, ARegion *UNUSED(ar))
+{
+ Scene *scene = CTX_data_scene(C);
+ RenderEngineType *type = RE_engines_find(scene->r.engine); /* In the future we should get that from Layers */
+
+ if (type->flag & RE_USE_OGL_PIPELINE) {
+ type->view_draw(NULL, C);
+ }
+ else {
+ // Offline Render engine
+ }
+}
+
+static void view3d_draw_view_new(const bContext *C, ARegion *ar, DrawData *UNUSED(draw_data))
+{
+
+ view3d_draw_setup_view(C, ar);
+
+ /* Only 100% compliant on new spec goes bellow */
+ view3d_render_pass(C, ar);
+
+ view3d_draw_grid(C, ar);
+ view3d_draw_manipulators(C, ar);
+ view3d_draw_region_info(C, ar);
+}
+
+
void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
+ Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
+ /* TODO layers - In the future we should get RE from Layers */
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
- if (IS_VIEWPORT_LEGACY(v3d)) {
+ if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_OGL_PIPELINE) == 0)) {
view3d_main_region_draw_legacy(C, ar);
return;
}
@@ -2113,12 +2145,20 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
if (!rv3d->viewport)
rv3d->viewport = GPU_viewport_create();
+ GPU_viewport_bind(rv3d->viewport, &ar->winrct, scene->r.engine);
+
/* 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, rv3d, &draw_data);
- view3d_draw_view(C, ar, &draw_data);
+
+ if (type->flag & RE_USE_OGL_PIPELINE)
+ view3d_draw_view_new(C, ar, &draw_data);
+ else
+ view3d_draw_view(C, ar, &draw_data);
+
+ GPU_viewport_unbind(rv3d->viewport);
v3d->flag |= V3D_INVALID_BACKBUF;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 3f78cfdb086..26756a5e410 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -60,6 +60,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_image.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_global.h"
@@ -292,7 +293,7 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
name = tmpstr;
}
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(BLF_default(), 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
@@ -310,6 +311,8 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
const char *msg_pin = " (Pinned)";
const char *msg_sep = " : ";
+ const int font_id = BLF_default();
+
char info[300];
char *s = info;
short offset = 1.5f * UI_UNIT_X + rect->xmin;
@@ -385,18 +388,18 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
/* 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);
+ UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
else
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
}
else {
/* no object */
if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
else
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
}
if (markern) {
@@ -411,10 +414,10 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
/* *********************** backdraw for selection *************** */
-static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d)
+static void backdrawview3d(Scene *scene, SceneLayer *sl, wmWindow *win, ARegion *ar, View3D *v3d)
{
RegionView3D *rv3d = ar->regiondata;
- struct Base *base = scene->basact;
+ struct Base *base = sl->basact;
int multisample_enabled;
BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
@@ -511,7 +514,7 @@ static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d
G.f |= G_BACKBUFSEL;
- if (base && (base->lay & v3d->lay))
+ if (base && ((base->flag & BASE_VISIBLED) != 0))
draw_object_backbufsel(scene, v3d, rv3d, base->object);
if (rv3d->gpuoffscreen)
@@ -556,7 +559,7 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h,
void ED_view3d_backbuf_validate(ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF)
- backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d);
+ backdrawview3d(vc->scene, vc->sl, vc->win, vc->ar, vc->v3d);
}
/**
@@ -1030,22 +1033,22 @@ static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
typedef struct View3DAfter {
struct View3DAfter *next, *prev;
- struct Base *base;
+ struct BaseLegacy *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)
+void ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag)
{
View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
- BLI_assert((base->flag & OB_FROMDUPLI) == 0);
+ BLI_assert((base->flag_legacy & 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)
+static void view3d_draw_transp(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d)
{
View3DAfter *v3da;
@@ -1053,7 +1056,7 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
v3d->transp = true;
while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
+ draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag);
MEM_freeN(v3da);
}
v3d->transp = false;
@@ -1063,7 +1066,7 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
}
/* clears zbuffer and draws it over */
-static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
+static void view3d_draw_xray(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear)
{
if (*clear && v3d->zbuf) {
glClear(GL_DEPTH_BUFFER_BIT);
@@ -1073,7 +1076,7 @@ static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear
v3d->xray = true;
View3DAfter *v3da;
while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
+ draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag);
MEM_freeN(v3da);
}
v3d->xray = false;
@@ -1081,7 +1084,7 @@ static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear
/* clears zbuffer and draws it over */
-static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear)
+static void view3d_draw_xraytransp(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, const bool clear)
{
if (clear && v3d->zbuf)
glClear(GL_DEPTH_BUFFER_BIT);
@@ -1093,7 +1096,7 @@ static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const
View3DAfter *v3da;
while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
+ draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag);
MEM_freeN(v3da);
}
@@ -1132,7 +1135,7 @@ static DupliObject *dupli_step(DupliObject *dob)
}
static void draw_dupli_objects_color(
- Scene *scene, ARegion *ar, View3D *v3d, Base *base,
+ Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *base,
const short dflag, const int color)
{
RegionView3D *rv3d = ar->regiondata;
@@ -1149,7 +1152,7 @@ static void draw_dupli_objects_color(
short dtx;
DupliApplyData *apply_data;
- if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
+ if ((base->flag & BASE_VISIBLED) == 0) return;
if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return;
if (dflag & DRAW_CONSTCOLOR) {
@@ -1159,7 +1162,8 @@ static void draw_dupli_objects_color(
UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb);
}
- tbase.flag = OB_FROMDUPLI | base->flag;
+ tbase.flag_legacy = OB_FROMDUPLI | base->flag_legacy;
+ tbase.flag = 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. */
@@ -1253,7 +1257,7 @@ static void draw_dupli_objects_color(
displist = glGenLists(1);
glNewList(displist, GL_COMPILE);
- draw_object(scene, ar, v3d, &tbase, dflag_dupli);
+ draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli);
glEndList();
use_displist = true;
@@ -1270,7 +1274,7 @@ static void draw_dupli_objects_color(
else {
copy_m4_m4(dob->ob->obmat, dob->mat);
GPU_begin_dupli_object(dob);
- draw_object(scene, ar, v3d, &tbase, dflag_dupli);
+ draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli);
GPU_end_dupli_object();
}
}
@@ -1292,17 +1296,17 @@ static void draw_dupli_objects_color(
glDeleteLists(displist, 1);
}
-void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
+void draw_dupli_objects(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *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;
+ int color = (base->flag & BASE_SELECTED) ? 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);
+ draw_dupli_objects_color(scene, sl, ar, v3d, base, 0, color);
}
/* XXX warning, not using gpu offscreen here */
@@ -1449,10 +1453,11 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
short flag = v3d->flag;
float glalphaclip = U.glalphaclip;
int obcenter_dia = U.obcenter_dia;
+ TODO_LAYER_CONTEXT; /* we should pass context, really */
+ SceneLayer *sl = BKE_scene_layer_active(scene);
/* 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 */
@@ -1483,21 +1488,21 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
Scene *sce_iter;
for (SETLOOPER(scene->set, sce_iter, base)) {
if (v3d->lay & base->lay) {
- draw_object(scene, ar, v3d, base, 0);
+ draw_object(scene, sl, ar, v3d, base, 0);
if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED);
}
}
}
}
- for (base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
/* dupli drawing */
if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED);
}
- draw_object(scene, ar, v3d, base, dflag_depth);
+ draw_object(scene, sl, ar, v3d, base, dflag_depth);
}
}
@@ -1518,7 +1523,7 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
+ draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth);
}
glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
}
@@ -1527,21 +1532,21 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
v3d->xray = false;
v3d->transp = true;
while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
+ draw_object(scene, sl, 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);
+ draw_object(scene, sl, 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);
+ draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth);
MEM_freeN(v3da);
}
@@ -1603,7 +1608,7 @@ static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d)
{
ListBase shadows;
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
World *world = scene->world;
SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL;
@@ -1737,8 +1742,9 @@ static void view3d_draw_objects(
const char **grid_unit,
const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
{
+ SceneLayer *sl = C ? CTX_data_scene_layer(C) : BKE_scene_layer_active(scene);
RegionView3D *rv3d = ar->regiondata;
- Base *base;
+ BaseLegacy *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);
@@ -1798,10 +1804,10 @@ static void view3d_draw_objects(
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);
+ draw_object(scene, sl, ar, v3d, base, dflag);
if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag, TH_UNDEFINED);
+ draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag, TH_UNDEFINED);
}
}
}
@@ -1810,13 +1816,13 @@ static void view3d_draw_objects(
}
if (draw_offscreen) {
- for (base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
/* dupli drawing */
if (base->object->transflag & OB_DUPLI)
- draw_dupli_objects(scene, ar, v3d, base);
+ draw_dupli_objects(scene, sl, ar, v3d, base);
- draw_object(scene, ar, v3d, base, 0);
+ draw_object(scene, sl, ar, v3d, base, 0);
}
}
}
@@ -1824,18 +1830,18 @@ static void view3d_draw_objects(
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) {
+ for (base = sl->object_bases.first; base; base = base->next) {
lay_used |= base->lay;
- if (v3d->lay & base->lay) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
/* dupli drawing */
if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects(scene, ar, v3d, base);
+ draw_dupli_objects(scene, sl, ar, v3d, base);
}
- if ((base->flag & SELECT) == 0) {
+ if ((base->flag & BASE_SELECTED) == 0) {
if (base->object != scene->obedit)
- draw_object(scene, ar, v3d, base, 0);
+ draw_object(scene, sl, ar, v3d, base, 0);
}
}
}
@@ -1844,10 +1850,10 @@ static void view3d_draw_objects(
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);
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) {
+ draw_object(scene, sl, ar, v3d, base, 0);
}
}
}
@@ -1869,7 +1875,7 @@ static void view3d_draw_objects(
}
/* transp and X-ray afterdraw stuff */
- if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
+ if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, sl, ar, v3d);
/* always do that here to cleanup depth buffers if none needed */
if (fx) {
@@ -1877,8 +1883,8 @@ static void view3d_draw_objects(
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 (v3d->afterdraw_xray.first) view3d_draw_xray(scene, sl, ar, v3d, &xrayclear);
+ if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, sl, ar, v3d, xrayclear);
if (fx && do_composite_xray) {
GPU_fx_compositor_XRay_resolve(fx);
@@ -2345,13 +2351,15 @@ void ED_scene_draw_fps(Scene *scene, const rcti *rect)
}
#endif
+ const int font_id = BLF_default();
+
/* is this more than half a frame behind? */
if (fps + 0.5f < (float)(FPS)) {
- UI_ThemeColor(TH_REDALERT);
+ UI_FontThemeColor(font_id, TH_REDALERT);
BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
}
else {
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
}
@@ -2533,7 +2541,7 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *
static void update_lods(Scene *scene, float camera_pos[3])
{
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
for (SETLOOPER(scene, sce_iter, base)) {
Object *ob = base->object;
@@ -2664,7 +2672,8 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
draw_view_icon(rv3d, &rect);
if (U.uiflag & USER_DRAWVIEWINFO) {
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
draw_selected_name(scene, ob, &rect);
}
}
@@ -2685,7 +2694,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
if (grid_unit) { /* draw below the viewport name */
char numstr[32] = "";
- UI_ThemeColor(TH_TEXT_HI);
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
if (v3d->grid != 1.0f) {
BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 921042229b0..a27434fdfd7 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -670,7 +670,7 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
/* object mode use boundbox centers */
View3D *v3d = CTX_wm_view3d(C);
- Base *base;
+ BaseLegacy *base;
unsigned int tot = 0;
float select_center[3];
@@ -2940,7 +2940,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- Base *base;
+ BaseLegacy *base;
float *curs;
const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
@@ -3045,7 +3045,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
/* hard-coded exception, we look for the one selected armature */
/* this is weak code this way, we should make a generic active/selection callback interface once... */
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
if (TESTBASELIB(v3d, base)) {
if (base->object->type == OB_ARMATURE)
@@ -3091,7 +3091,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ok_dist = 0; /* don't zoom */
}
else {
- Base *base;
+ BaseLegacy *base;
for (base = FIRSTBASE; base; base = base->next) {
if (TESTBASE(v3d, base)) {
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 92e3fb5946b..fb109e98a7e 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -284,9 +284,10 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ToolSettings *ts = CTX_data_tool_settings(C);
PointerRNA v3dptr, toolsptr, sceneptr;
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
Object *obedit = CTX_data_edit_object(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
uiBlock *block;
@@ -373,11 +374,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
}
if (obedit == NULL && v3d->localvd == NULL) {
- unsigned int ob_lay = ob ? ob->lay : 0;
-
- /* Layers */
- uiTemplateLayers(layout, v3d->scenelock ? &sceneptr : &v3dptr, "layers", &v3dptr, "layers_used", ob_lay);
-
/* Scene lock */
uiItemR(layout, &v3dptr, "lock_camera_and_layers", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 21a3f16c510..5f29e91143a 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -38,6 +38,7 @@
struct ARegion;
struct ARegionType;
struct BoundBox;
+struct Batch;
struct DerivedMesh;
struct Object;
struct SmokeDomainSettings;
@@ -46,6 +47,7 @@ struct bContext;
struct bMotionPath;
struct bPoseChannel;
struct Mesh;
+struct SceneLayer;
struct wmManipulatorGroupType;
struct wmOperatorType;
struct wmWindowManager;
@@ -142,14 +144,14 @@ 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_object(Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, BaseLegacy *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 draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]);
+void draw_object_wire_color(Scene *scene, struct SceneLayer *, Base *base, unsigned char r_ob_wire_col[4]);
void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]);
void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4],
@@ -179,7 +181,7 @@ enum {
int view3d_effective_drawtype(const struct View3D *v3d);
/* drawarmature.c */
-bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
+bool draw_armature(Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
const short dt, const short dflag, const unsigned char ob_wire_col[4],
const bool is_outline);
@@ -210,7 +212,7 @@ void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar);
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 ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag);
void circ(float x, float y, float rad);
void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect);
@@ -334,7 +336,7 @@ void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool
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);
+void draw_dupli_objects(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *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);
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 7540e5ad180..4a4d008f779 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -43,6 +43,8 @@
#include "BIF_gl.h"
+#include "GPU_immediate.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -280,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE,
+ CTX_data_main(C), CTX_data_scene(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
@@ -456,28 +458,38 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
glEnable(GL_BLEND);
- cpack(is_act ? color_act : color_base);
-
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- glBegin(GL_LINE_STRIP);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ imm_cpack(is_act ? color_act : color_base);
+
+ immBegin(GL_LINE_STRIP, 3);
+
for (j = 0; j < 3; j++) {
- glVertex2fv(co_ss[j]);
+ immVertex2fv(pos, co_ss[j]);
}
- glEnd();
- cpack(0xaaaaaa);
+
+ immEnd();
+
+ imm_cpack(0xaaaaaa);
setlinestyle(3);
- glBegin(GL_LINE_STRIP);
+
+ immBegin(GL_LINE_STRIP, 3);
+
for (j = 0; j < 3; j++) {
- glVertex2fv(co_ss[j]);
+ immVertex2fv(pos, co_ss[j]);
}
- glEnd();
+
+ immEnd();
+
setlinestyle(0);
/* arc */
{
float dir_tmp[3];
float co_tmp[3];
- float arc_ss_coords[ARC_STEPS + 1][2];
+ float arc_ss_coord[2];
float dir_a[3];
float dir_b[3];
@@ -501,45 +513,19 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
copy_v3_v3(dir_tmp, dir_a);
- glColor3ubv(color_wire);
+ immUniformColor3ubv(color_wire);
+
+ immBegin(GL_LINE_STRIP, arc_steps + 1);
for (j = 0; j <= arc_steps; j++) {
madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
- ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP);
mul_qt_v3(quat, dir_tmp);
- }
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords);
- glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
-
- /* text */
- {
- char numstr[256];
- float numstr_size[2];
- float pos[2];
- const int prec = 2; /* XXX, todo, make optional */
-
- ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
-
- BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
- pos[0] = co_ss[1][0] + (cap_size * 2.0f);
- pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
+ immVertex2fv(pos, arc_ss_coord);
+ }
- /* draw text (bg) */
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox(
- pos[0] - bg_margin, pos[1] - bg_margin,
- pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
- bg_radius, color_back);
- /* draw text */
- glColor3ubv(color_text);
- BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
- BLF_rotation(blf_mono_font, 0.0f);
- BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ immEnd();
}
/* capping */
@@ -560,74 +546,88 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
glEnable(GL_BLEND);
- glColor3ubv(color_wire);
+ immUniformColor3ubv(color_wire);
- glBegin(GL_LINES);
+ immBegin(GL_LINES, 8);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(pos, cap);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
- glVertex2fv(cap);
+ immVertex2fv(pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
- glVertex2fv(cap);
+ immVertex2fv(pos, cap);
/* angle vertex */
- glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
- glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
- glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
- glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
- glEnd();
+ immVertex2f(pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+
+ immEnd();
glDisable(GL_BLEND);
}
- }
- else {
- glBegin(GL_LINE_STRIP);
- for (j = 0; j < 3; j += 2) {
- glVertex2fv(co_ss[j]);
- }
- glEnd();
- cpack(0xaaaaaa);
- setlinestyle(3);
- glBegin(GL_LINE_STRIP);
- for (j = 0; j < 3; j += 2) {
- glVertex2fv(co_ss[j]);
- }
- glEnd();
- setlinestyle(0);
- sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
+ immUnbindProgram();
/* text */
{
char numstr[256];
float numstr_size[2];
- const int prec = 6; /* XXX, todo, make optional */
- float pos[2];
+ float posit[2];
+ const int prec = 2; /* XXX, todo, make optional */
ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
- mid_v2_v2v2(pos, co_ss[0], co_ss[2]);
-
- /* center text */
- pos[0] -= numstr_size[0] / 2.0f;
- pos[1] -= numstr_size[1] / 2.0f;
+ posit[0] = co_ss[1][0] + (cap_size * 2.0f);
+ posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
/* draw text (bg) */
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox(pos[0] - bg_margin, pos[1] - bg_margin,
- pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
- bg_radius, color_back);
+ UI_draw_roundbox(
+ posit[0] - bg_margin, posit[1] - bg_margin,
+ posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1],
+ bg_radius, color_back);
/* draw text */
- glColor3ubv(color_text);
- BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
+ BLF_color3ubv(blf_mono_font, color_text);
+ BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
+ BLF_rotation(blf_mono_font, 0.0f);
BLF_draw(blf_mono_font, numstr, sizeof(numstr));
}
+ }
+ else {
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ imm_cpack(is_act ? color_act : color_base);
+
+ immBegin(GL_LINE_STRIP, 2);
+
+ for (j = 0; j < 3; j += 2) {
+ immVertex2fv(pos, co_ss[j]);
+ }
+
+ immEnd();
+
+ imm_cpack(0xaaaaaa);
+ setlinestyle(3);
+
+ immBegin(GL_LINE_STRIP, 2);
+
+ for (j = 0; j < 3; j += 2) {
+ immVertex2fv(pos, co_ss[j]);
+ }
+
+ immEnd();
+
+ setlinestyle(0);
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
/* capping */
{
@@ -637,22 +637,55 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
normalize_v2(rot_90_vec);
glEnable(GL_BLEND);
- glColor3ubv(color_wire);
- glBegin(GL_LINES);
+ immUniformColor3ubv(color_wire);
+
+ immBegin(GL_LINES, 4);
+
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(pos, cap);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
- glVertex2fv(cap);
+ immVertex2fv(pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
- glVertex2fv(cap);
- glEnd();
+ immVertex2fv(pos, cap);
+
+ immEnd();
glDisable(GL_BLEND);
}
+
+ immUnbindProgram();
+
+ /* text */
+ {
+ char numstr[256];
+ float numstr_size[2];
+ const int prec = 6; /* XXX, todo, make optional */
+ float posit[2];
+
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+
+ BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
+
+ mid_v2_v2v2(posit, co_ss[0], co_ss[2]);
+
+ /* center text */
+ posit[0] -= numstr_size[0] / 2.0f;
+ posit[1] -= numstr_size[1] / 2.0f;
+
+ /* draw text (bg) */
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox(posit[0] - bg_margin, posit[1] - bg_margin,
+ posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1],
+ bg_radius, color_back);
+ /* draw text */
+ BLF_color3ubv(blf_mono_font, color_text);
+ BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
}
}
@@ -671,8 +704,14 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
float co_ss[3];
ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP);
- cpack(color_act);
- circ(co_ss[0], co_ss[1], size * U.pixelsize);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ imm_cpack(color_act);
+
+ imm_draw_lined_circle(pos, co_ss[0], co_ss[1], size * U.pixelsize, 32);
+
+ immUnbindProgram();
}
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 3239d07553f..60bf078acc3 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -64,11 +64,13 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_editmesh.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BKE_utildefines.h"
@@ -109,6 +111,7 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc)
memset(vc, 0, sizeof(ViewContext));
vc->ar = CTX_wm_region(C);
vc->scene = CTX_data_scene(C);
+ vc->sl = CTX_data_scene_layer(C);
vc->v3d = CTX_wm_view3d(C);
vc->win = CTX_wm_window(C);
vc->rv3d = CTX_wm_region_view3d(C);
@@ -399,13 +402,13 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[]
}
}
-static void object_deselect_all_visible(Scene *scene, View3D *v3d)
+static void object_deselect_all_visible(SceneLayer *sl)
{
Base *base;
- for (base = scene->base.first; base; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- ED_base_object_select(base, BA_DESELECT);
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE_NEW(base)) {
+ ED_object_base_select(base, BA_DESELECT);
}
}
}
@@ -416,15 +419,14 @@ static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], cons
Base *base;
if (extend == false && select)
- object_deselect_all_visible(vc->scene, vc->v3d);
+ object_deselect_all_visible(vc->sl);
- for (base = vc->scene->base.first; base; base = base->next) {
- if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */
+ for (base = vc->sl->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE_NEW(base)) { /* use this to avoid un-needed lasso lookups */
if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
- base->object->flag = base->flag;
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
}
if (vc->obact == base->object && (base->object->mode & OB_MODE_POSE)) {
@@ -1017,8 +1019,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
if (!toggle) {
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if (base->flag & SELECT) {
- ED_base_object_select(base, BA_DESELECT);
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
changed = true;
}
}
@@ -1029,8 +1031,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
{
/* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
if (STREQ(name, base->object->id.name + 2)) {
- ED_base_object_activate(C, base);
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_activate(C, base);
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -1074,14 +1076,12 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
}
-static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */
+static void deselectall_except(SceneLayer *sl, Base *b) /* deselect all except b */
{
- Base *base;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->flag & SELECT) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_SELECTED) {
if (b != base) {
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
}
}
}
@@ -1092,7 +1092,8 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
short baseCount = 0;
bool ok;
LinkNode *linklist = NULL;
-
+
+ /* handle base->selcol */
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
ok = false;
@@ -1278,8 +1279,7 @@ static short mixed_bones_object_selectbuffer(
static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits,
Base *startbase, bool has_bones, bool do_nearest)
{
- Scene *scene = vc->scene;
- View3D *v3d = vc->v3d;
+ SceneLayer *sl = vc->sl;
Base *base, *basact = NULL;
int a;
@@ -1299,7 +1299,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int
}
else {
/* only exclude active object when it is selected... */
- if (BASACT && (BASACT->flag & SELECT) && hits > 1) notcol = BASACT->selcol;
+ if (BASACT_NEW && (BASACT_NEW->flag & BASE_SELECTED) && hits > 1) notcol = BASACT_NEW->selcol;
for (a = 0; a < hits; a++) {
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
@@ -1309,9 +1309,9 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int
}
}
- base = FIRSTBASE;
+ base = FIRSTBASE_NEW;
while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
+ if (BASE_SELECTABLE_NEW(base)) {
if (base->selcol == selcol) break;
}
base = base->next;
@@ -1324,13 +1324,13 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int
while (base) {
/* skip objects with select restriction, to prevent prematurely ending this loop
* with an un-selectable choice */
- if (base->object->restrictflag & OB_RESTRICT_SELECT) {
+ if ((base->flag & BASE_SELECTABLED) == 0) {
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE_NEW;
if (base == startbase) break;
}
- if (BASE_SELECTABLE(v3d, base)) {
+ if (BASE_SELECTABLE_NEW(base)) {
for (a = 0; a < hits; a++) {
if (has_bones) {
/* skip non-bone objects */
@@ -1349,7 +1349,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int
if (basact) break;
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE_NEW;
if (base == startbase) break;
}
}
@@ -1374,7 +1374,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
- basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene->base.first, has_bones, do_nearest);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.sl->object_bases.first, has_bones, do_nearest);
}
return basact;
@@ -1406,8 +1406,8 @@ static bool ed_object_select_pick(
{
ViewContext vc;
ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
bool is_obedit;
float dist = ED_view3d_select_dist_px() * 1.3333f;
@@ -1426,8 +1426,8 @@ static bool ed_object_select_pick(
}
/* always start list from basact in wire mode */
- startbase = FIRSTBASE;
- if (BASACT && BASACT->next) startbase = BASACT->next;
+ startbase = FIRSTBASE_NEW;
+ if (BASACT_NEW && BASACT_NEW->next) startbase = BASACT_NEW->next;
/* This block uses the control key to make the object selected by its center point rather than its contents */
/* in editmode do not activate */
@@ -1440,13 +1440,13 @@ static bool ed_object_select_pick(
else {
base = startbase;
while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
+ if (BASE_SELECTABLE_NEW(base)) {
float screen_co[2];
if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
- if (base == BASACT) dist_temp += 10.0f;
+ if (base == BASACT_NEW) dist_temp += 10.0f;
if (dist_temp < dist) {
dist = dist_temp;
basact = base;
@@ -1455,7 +1455,7 @@ static bool ed_object_select_pick(
}
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE_NEW;
if (base == startbase) break;
}
}
@@ -1482,7 +1482,7 @@ static bool ed_object_select_pick(
if (has_bones && basact) {
if (basact->object->type == OB_CAMERA) {
- if (BASACT == basact) {
+ if (BASACT_NEW == basact) {
int i, hitresult;
bool changed = false;
@@ -1520,8 +1520,8 @@ static bool ed_object_select_pick(
changed = true;
}
- basact->flag |= SELECT;
- basact->object->flag = basact->flag;
+ basact->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(basact);
retval = true;
@@ -1544,22 +1544,22 @@ static bool ed_object_select_pick(
/* we make the armature selected:
* not-selected active object in posemode won't work well for tools */
- basact->flag |= SELECT;
- basact->object->flag = basact->flag;
+ basact->flag |= BASE_SELECTED;
+ BKE_scene_base_flag_sync_from_base(basact);
retval = true;
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
/* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */
- if (BASACT && (BASACT->object->mode & OB_MODE_WEIGHT_PAINT)) {
+ if (BASACT_NEW && (BASACT_NEW->object->mode & OB_MODE_WEIGHT_PAINT)) {
/* prevent activating */
basact = NULL;
}
}
/* prevent bone selecting to pass on to object selecting */
- if (basact == BASACT)
+ if (basact == BASACT_NEW)
basact = NULL;
}
}
@@ -1571,37 +1571,37 @@ static bool ed_object_select_pick(
if (vc.obedit) {
/* only do select */
- deselectall_except(scene, basact);
- ED_base_object_select(basact, BA_SELECT);
+ deselectall_except(sl, basact);
+ ED_object_base_select(basact, BA_SELECT);
}
/* also prevent making it active on mouse selection */
- else if (BASE_SELECTABLE(v3d, basact)) {
+ else if (BASE_SELECTABLE_NEW(basact)) {
- oldbasact = BASACT;
+ oldbasact = BASACT_NEW;
if (extend) {
- ED_base_object_select(basact, BA_SELECT);
+ ED_object_base_select(basact, BA_SELECT);
}
else if (deselect) {
- ED_base_object_select(basact, BA_DESELECT);
+ ED_object_base_select(basact, BA_DESELECT);
}
else if (toggle) {
- if (basact->flag & SELECT) {
+ if (basact->flag & BASE_SELECTED) {
if (basact == oldbasact) {
- ED_base_object_select(basact, BA_DESELECT);
+ ED_object_base_select(basact, BA_DESELECT);
}
}
else {
- ED_base_object_select(basact, BA_SELECT);
+ ED_object_base_select(basact, BA_SELECT);
}
}
else {
- deselectall_except(scene, basact);
- ED_base_object_select(basact, BA_SELECT);
+ deselectall_except(sl, basact);
+ ED_object_base_select(basact, BA_SELECT);
}
if ((oldbasact != basact) && (is_obedit == false)) {
- ED_base_object_activate(C, basact); /* adds notifier */
+ ED_object_base_activate(C, basact); /* adds notifier */
}
}
@@ -2031,7 +2031,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
CTX_DATA_END;
}
else {
- object_deselect_all_visible(vc->scene, vc->v3d);
+ object_deselect_all_visible(vc->sl);
}
}
@@ -2051,7 +2051,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
*/
if (hits > 0) { /* no need to loop if there's no hit */
- Base *base;
+ BaseLegacy *base;
col = vbuffer + 3;
for (base = vc->scene->base.first; base && hits; base = base->next) {
@@ -2786,22 +2786,22 @@ static void obedit_circle_select(ViewContext *vc, const bool select, const int m
static bool object_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
{
- Scene *scene = vc->scene;
+ SceneLayer *sl = vc->sl;
const float radius_squared = rad * rad;
const float mval_fl[2] = {mval[0], mval[1]};
bool changed = false;
- const int select_flag = select ? SELECT : 0;
+ const int select_flag = select ? BASE_SELECTED : 0;
Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if (BASE_SELECTABLE_NEW(base) && ((base->flag & BASE_SELECTED) != select_flag)) {
float screen_co[2];
if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
changed = true;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 8582952d1a0..53c91936913 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -1091,28 +1091,27 @@ void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d)
}
}
-static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, bool use_obedit_skip)
+static void view3d_select_loop(ViewContext *vc, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, bool use_obedit_skip)
{
short code = 1;
char dt;
short dtx;
if (vc->obedit && vc->obedit->type == OB_MBALL) {
- draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
+ draw_object(scene, sl, ar, v3d, BASACT_NEW, DRAW_PICKING | DRAW_CONSTCOLOR);
}
else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
/* if not drawing sketch, draw bones */
if (!BDR_drawSketchNames(vc)) {
- draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
+ draw_object(scene, sl, ar, v3d, BASACT_NEW, DRAW_PICKING | DRAW_CONSTCOLOR);
}
}
else {
Base *base;
v3d->xray = true; /* otherwise it postpones drawing */
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & v3d->lay) {
-
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
(use_obedit_skip && (scene->obedit->data == base->object->data)))
{
@@ -1122,7 +1121,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi
base->selcol = code;
if (GPU_select_load_id(code)) {
- draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR);
+ draw_object(scene, sl, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR);
/* we draw duplicators for selection too */
if ((base->object->transflag & OB_DUPLI)) {
@@ -1130,7 +1129,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi
DupliObject *dob;
Base tbase;
- tbase.flag = OB_FROMDUPLI;
+ tbase.flag_legacy = OB_FROMDUPLI;
lb = object_duplilist(G.main->eval_ctx, scene, base->object);
for (dob = lb->first; dob; dob = dob->next) {
@@ -1145,7 +1144,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi
dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
- draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
+ draw_object(scene, sl, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
tbase.object->dt = dt;
tbase.object->dtx = dtx;
@@ -1173,6 +1172,7 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi
short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, bool do_nearest)
{
Scene *scene = vc->scene;
+ SceneLayer *sl = vc->sl;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
rctf rect;
@@ -1209,7 +1209,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
else
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_ALL, 0);
- view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
+ view3d_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip);
hits = GPU_select_end();
@@ -1217,7 +1217,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
if (do_passes) {
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
- view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
+ view3d_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip);
GPU_select_end();
}
@@ -1319,7 +1319,7 @@ static bool view3d_localview_init(
ReportList *reports)
{
View3D *v3d = sa->spacedata.first;
- Base *base;
+ BaseLegacy *base;
float min[3], max[3], box[3], mid[3];
float size = 0.0f;
unsigned int locallay;
@@ -1422,7 +1422,7 @@ static bool view3d_localview_init(
if (base->lay & locallay) {
base->lay -= locallay;
if (base->lay == 0) base->lay = v3d->layact;
- if (base->object != scene->obedit) base->flag |= SELECT;
+ if (base->object != scene->obedit) base->flag_legacy |= SELECT;
base->object->lay = base->lay;
}
}
@@ -1493,7 +1493,7 @@ static bool view3d_localview_exit(
Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx)
{
View3D *v3d = sa->spacedata.first;
- struct Base *base;
+ struct BaseLegacy *base;
unsigned int locallay;
if (v3d->localvd) {
@@ -1510,7 +1510,7 @@ static bool view3d_localview_exit(
base->lay -= locallay;
if (base->lay == 0) base->lay = v3d->layact;
if (base->object != scene->obedit) {
- base->flag |= SELECT;
+ base->flag_legacy |= SELECT;
base->object->flag |= SELECT;
}
base->object->lay = base->lay;
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 4131a5c33c7..d4e78035b84 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -599,7 +599,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), walk->scene, SNAP_OBJECT_USE_CACHE,
+ CTX_data_main(C), walk->scene, 0,
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 5b1dcf92c29..fb1543c5deb 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1852,8 +1852,9 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
int xco, yco;
ED_region_visible_rect(ar, &rect);
-
- BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+
+ const int font_id = BLF_default();
+ BLF_width_and_height(font_id, 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);
@@ -1861,7 +1862,9 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
/* warning text (to clarify meaning of overlays)
* - original color was red to match the icon, but that clashes badly with a less nasty border
*/
- UI_ThemeColorShade(TH_TEXT_HI, -50);
+ unsigned char color[3];
+ UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color);
+ BLF_color3ubv(font_id, color);
#ifdef WITH_INTERNATIONAL
BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#else
@@ -1884,7 +1887,8 @@ static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *ar, vo
{
TransInfo *t = arg;
Scene *scene = t->scene;
- Object *ob = OBACT;
+ SceneLayer *sl = t->sl;
+ Object *ob = OBACT_NEW;
/* draw autokeyframing hint in the corner
* - only draw if enabled (advanced users may be distracted/annoyed),
@@ -3721,6 +3725,12 @@ static void initRotation(TransInfo *t)
copy_v3_v3(t->axis_orig, t->axis);
}
+/**
+ * Applies values of rotation to `td->loc` and `td->ext->quat`
+ * based on a rotation matrix (mat) and a pivot (center).
+ *
+ * Protected axis and other transform settings are taken into account.
+ */
static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], const float *center)
{
float vec[3], totmat[3][3], smat[3][3];
@@ -4338,9 +4348,22 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
{
TransData *td = t->data;
float tvec[3];
- int i;
- for (i = 0; i < t->total; i++, td++) {
+ /* The ideal would be "apply_snap_align_rotation" only when a snap point is found
+ * so, maybe inside this function is not the best place to apply this rotation.
+ * but you need "handle snapping rotation before doing the translation" (really?) */
+ const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT);
+ float pivot[3];
+ if (apply_snap_align_rotation) {
+ copy_v3_v3(pivot, t->tsnap.snapTarget);
+ /* The pivot has to be in local-space (see T49494) */
+ if (t->flag & (T_EDIT | T_POSE)) {
+ Object *ob = t->obedit ? t->obedit : t->poseobj;
+ mul_m4_v3(ob->imat, pivot);
+ }
+ }
+
+ for (int i = 0; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
@@ -4351,7 +4374,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
bool use_rotate_offset = false;
/* handle snapping rotation before doing the translation */
- if (usingSnappingNormal(t)) {
+ if (apply_snap_align_rotation) {
float mat[3][3];
if (validSnappingNormal(t)) {
@@ -4369,7 +4392,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
unit_m3(mat);
}
- ElementRotation_ex(t, td, mat, t->tsnap.snapTarget);
+ ElementRotation_ex(t, td, mat, pivot);
if (td->loc) {
use_rotate_offset = true;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index f250a7abf7c..31af54c030b 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -84,8 +84,8 @@ typedef struct TransSnap {
bool peel;
bool snap_spatial_grid;
short status;
- float snapPoint[3]; /* snapping from this point */
- float snapTarget[3]; /* to this point */
+ float snapPoint[3]; /* snapping from this point (in global-space)*/
+ float snapTarget[3]; /* to this point (in global-space)*/
float snapNormal[3];
char snapNodeBorder;
ListBase points;
@@ -461,6 +461,7 @@ typedef struct TransInfo {
struct ScrArea *sa;
struct ARegion *ar;
struct Scene *scene;
+ struct SceneLayer *sl;
struct ToolSettings *settings;
struct wmTimer *animtimer;
struct wmKeyMap *keymap; /* so we can do lookups for header text */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index c4fa84513c3..d123d9eb3c1 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -40,9 +40,10 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
@@ -715,7 +716,6 @@ void drawConstraint(TransInfo *t)
else {
if (tc->mode & CON_SELECT) {
float vec[3];
- char col2[3] = {255, 255, 255};
int depth_test_enabled;
convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1]));
@@ -725,19 +725,26 @@ void drawConstraint(TransInfo *t)
drawLine(t, t->center_global, tc->mtx[1], 'Y', 0);
drawLine(t, t->center_global, tc->mtx[2], 'Z', 0);
- glColor3ubv((GLubyte *)col2);
-
depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
if (depth_test_enabled)
glDisable(GL_DEPTH_TEST);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ub(255, 255, 255);
+
setlinestyle(1);
- glBegin(GL_LINES);
- glVertex3fv(t->center_global);
- glVertex3fv(vec);
- glEnd();
+
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, t->center_global);
+ immVertex3fv(pos, vec);
+ immEnd();
+
setlinestyle(0);
+ immUnbindProgram();
+
if (depth_test_enabled)
glEnable(GL_DEPTH_TEST);
}
@@ -762,8 +769,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
float tmat[4][4], imat[4][4];
int depth_test_enabled;
- UI_ThemeColor(TH_GRID);
-
if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) {
copy_m4_m4(tmat, rv3d->viewmat);
invert_m4_m4(imat, tmat);
@@ -796,10 +801,17 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
if (depth_test_enabled)
glDisable(GL_DEPTH_TEST);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_GRID);
+
set_inverted_drawing(1);
- drawcircball(GL_LINE_LOOP, t->center_global, t->prop_size, imat);
+ imm_drawcircball(t->center_global, t->prop_size, imat, pos);
set_inverted_drawing(0);
+ immUnbindProgram();
+
if (depth_test_enabled)
glEnable(GL_DEPTH_TEST);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 3e355deef33..b68b3365e46 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -72,6 +72,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
+#include "BKE_layer.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -2381,7 +2382,12 @@ static void createTransEditVerts(TransInfo *t)
editmesh_set_connectivity_distance(em->bm, mtx, dists);
}
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ /* Only in case of rotation and resize, we want the elements of the edited
+ * object to behave as groups whose pivot are the individual origins
+ *
+ * TODO: use island_info to detect the closest point when the "Snap Target"
+ * in Blender UI is "Closest" */
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) {
island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map);
}
@@ -5346,12 +5352,11 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
/* it deselects Bases, so we have to call the clear function always after */
static void set_trans_object_base_flags(TransInfo *t)
{
- Scene *scene = t->scene;
- View3D *v3d = t->view;
+ SceneLayer *sl = t->sl;
/*
* if Base selected and has parent selected:
- * base->flag = BA_WAS_SEL
+ * base->flag_legacy = BA_WAS_SEL
*/
Base *base;
@@ -5360,32 +5365,32 @@ static void set_trans_object_base_flags(TransInfo *t)
return;
/* makes sure base flags and object flags are identical */
- BKE_scene_base_flag_to_objects(t->scene);
+ BKE_scene_base_flag_to_objects(t->sl);
/* Make sure depsgraph is here. */
DAG_scene_relations_update(G.main, t->scene);
/* handle pending update events, otherwise they got copied below */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = sl->object_bases.first; base; base = base->next) {
if (base->object->recalc & OB_RECALC_ALL) {
/* TODO(sergey): Ideally, it's not needed. */
BKE_object_handle_update(G.main->eval_ctx, t->scene, base->object);
}
}
- for (base = scene->base.first; base; base = base->next) {
- base->flag &= ~BA_WAS_SEL;
+ for (base = sl->object_bases.first; base; base = base->next) {
+ base->flag_legacy &= ~BA_WAS_SEL;
- if (TESTBASELIB_BGMODE(v3d, scene, base)) {
+ if (TESTBASELIB_BGMODE_NEW(base)) {
Object *ob = base->object;
Object *parsel = ob->parent;
/* if parent selected, deselect */
while (parsel) {
- if (parsel->flag & SELECT) {
- Base *parbase = BKE_scene_base_find(scene, parsel);
+ Base *parbase = BKE_scene_layer_base_find(sl, parsel);
+ if (parbase->flag & BASE_SELECTED) {
if (parbase) { /* in rare cases this can fail */
- if (TESTBASELIB_BGMODE(v3d, scene, parbase)) {
+ if (TESTBASELIB_BGMODE_NEW(parbase)) {
break;
}
}
@@ -5398,11 +5403,11 @@ static void set_trans_object_base_flags(TransInfo *t)
if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
{
- base->flag |= BA_TRANSFORM_CHILD;
+ base->flag_legacy |= BA_TRANSFORM_CHILD;
}
else {
- base->flag &= ~SELECT;
- base->flag |= BA_WAS_SEL;
+ base->flag &= ~BASE_SELECTED;
+ base->flag_legacy |= BA_WAS_SEL;
}
}
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -5411,11 +5416,11 @@ static void set_trans_object_base_flags(TransInfo *t)
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = sl->object_bases.first; base; base = base->next) {
if (base->object->recalc & OB_RECALC_OB)
- base->flag |= BA_HAS_RECALC_OB;
+ base->flag_legacy |= BA_HAS_RECALC_OB;
if (base->object->recalc & OB_RECALC_DATA)
- base->flag |= BA_HAS_RECALC_DATA;
+ base->flag_legacy |= BA_HAS_RECALC_DATA;
}
}
@@ -5437,8 +5442,7 @@ static bool mark_children(Object *ob)
static int count_proportional_objects(TransInfo *t)
{
int total = 0;
- Scene *scene = t->scene;
- View3D *v3d = t->view;
+ SceneLayer *sl = t->sl;
Base *base;
/* rotations around local centers are allowed to propagate, so we take all objects */
@@ -5446,8 +5450,8 @@ static int count_proportional_objects(TransInfo *t)
(t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)))
{
/* mark all parents */
- for (base = scene->base.first; base; base = base->next) {
- if (TESTBASELIB_BGMODE(v3d, scene, base)) {
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if (TESTBASELIB_BGMODE_NEW(base)) {
Object *parent = base->object->parent;
/* flag all parents */
@@ -5459,22 +5463,24 @@ static int count_proportional_objects(TransInfo *t)
}
/* mark all children */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = sl->object_bases.first; base; base = base->next) {
/* all base not already selected or marked that is editable */
- if ((base->object->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- (BASE_EDITABLE_BGMODE(v3d, scene, base)))
+ if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 &&
+ (BASE_EDITABLE_BGMODE_NEW(base)))
{
mark_children(base->object);
}
}
}
- for (base = scene->base.first; base; base = base->next) {
+ for (base = sl->object_bases.first; base; base = base->next) {
Object *ob = base->object;
/* if base is not selected, not a parent of selection or not a child of selection and it is editable */
- if ((ob->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- (BASE_EDITABLE_BGMODE(v3d, scene, base)))
+ if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 &&
+ (BASE_EDITABLE_BGMODE_NEW(base)))
{
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -5489,11 +5495,11 @@ static int count_proportional_objects(TransInfo *t)
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = sl->object_bases.first; base; base = base->next) {
if (base->object->recalc & OB_RECALC_OB)
- base->flag |= BA_HAS_RECALC_OB;
+ base->flag_legacy |= BA_HAS_RECALC_OB;
if (base->object->recalc & OB_RECALC_DATA)
- base->flag |= BA_HAS_RECALC_DATA;
+ base->flag_legacy |= BA_HAS_RECALC_DATA;
}
return total;
@@ -5501,14 +5507,15 @@ static int count_proportional_objects(TransInfo *t)
static void clear_trans_object_base_flags(TransInfo *t)
{
- Scene *sce = t->scene;
+ SceneLayer *sl = t->sl;
Base *base;
- for (base = sce->base.first; base; base = base->next) {
- if (base->flag & BA_WAS_SEL)
- base->flag |= SELECT;
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if (base->flag_legacy & BA_WAS_SEL) {
+ base->flag |= BASE_SELECTED;
+ }
- base->flag &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
+ base->flag_legacy &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
}
}
@@ -6426,7 +6433,7 @@ static void createTransObject(bContext *C, TransInfo *t)
if (is_prop_edit) {
View3D *v3d = t->view;
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
@@ -7880,7 +7887,8 @@ static void createTransGPencil(bContext *C, TransInfo *t)
void createTransData(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
- Object *ob = OBACT;
+ SceneLayer *sl = t->sl;
+ Object *ob = OBACT_NEW;
/* if tests must match recalcData for correct updates */
if (t->options & CTX_TEXTURE) {
@@ -8040,10 +8048,9 @@ void createTransData(bContext *C, TransInfo *t)
* lines below just check is also visible */
Object *ob_armature = modifiers_isDeformedByArmature(ob);
if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
- Base *base_arm = BKE_scene_base_find(t->scene, ob_armature);
+ Base *base_arm = BKE_scene_layer_base_find(t->sl, ob_armature);
if (base_arm) {
- View3D *v3d = t->view;
- if (BASE_VISIBLE(v3d, base_arm)) {
+ if (BASE_VISIBLE_NEW(base_arm)) {
createTransPose(t, ob_armature);
}
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 6de5cf112d2..2c10ee61466 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -62,8 +62,7 @@
#include "RNA_access.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_immediate.h"
#include "BIK_api.h"
@@ -315,7 +314,7 @@ static bool fcu_test_selected(FCurve *fcu)
/* helper for recalcData() - for Action Editor transforms */
static void recalcData_actedit(TransInfo *t)
{
- Scene *scene = t->scene;
+ SceneLayer *sl= t->sl;
SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
bAnimContext ac = {NULL};
@@ -326,7 +325,7 @@ static void recalcData_actedit(TransInfo *t)
/* initialize relevant anim-context 'context' data from TransInfo data */
/* NOTE: sync this with the code in ANIM_animdata_get_context() */
ac.scene = t->scene;
- ac.obact = OBACT;
+ ac.obact = OBACT_NEW;
ac.sa = t->sa;
ac.ar = t->ar;
ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
@@ -363,7 +362,7 @@ static void recalcData_actedit(TransInfo *t)
static void recalcData_graphedit(TransInfo *t)
{
SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
- Scene *scene;
+ SceneLayer *sl = t->sl;
ListBase anim_data = {NULL, NULL};
bAnimContext ac = {NULL};
@@ -374,8 +373,8 @@ static void recalcData_graphedit(TransInfo *t)
/* initialize relevant anim-context 'context' data from TransInfo data */
/* NOTE: sync this with the code in ANIM_animdata_get_context() */
- scene = ac.scene = t->scene;
- ac.obact = OBACT;
+ ac.scene = t->scene;
+ ac.obact = OBACT_NEW;
ac.sa = t->sa;
ac.ar = t->ar;
ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
@@ -709,7 +708,7 @@ 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;
+ BaseLegacy *base = t->scene->basact;
if (t->obedit) {
if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
@@ -1050,14 +1049,19 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
UI_GetThemeColor3ubv(TH_GRID, col);
}
UI_make_axis_color(col, col2, axis);
- glColor3ubv(col2);
-
- setlinestyle(0);
- glBegin(GL_LINES);
- glVertex3fv(v1);
- glVertex3fv(v2);
- glEnd();
-
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(col2);
+
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ immUnbindProgram();
+
glPopMatrix();
}
}
@@ -1104,6 +1108,7 @@ static int initTransInfo_edit_pet_to_flag(const int proportional)
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
Scene *sce = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ToolSettings *ts = CTX_data_tool_settings(C);
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
@@ -1113,6 +1118,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
PropertyRNA *prop;
t->scene = sce;
+ t->sl = sl;
t->sa = sa;
t->ar = ar;
t->obedit = obedit;
@@ -1768,8 +1774,8 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
}
else if (t->flag & T_POSE) {
- Scene *scene = t->scene;
- Object *ob = OBACT;
+ SceneLayer *sl = t->sl;
+ Object *ob = OBACT_NEW;
if (ob) {
bPoseChannel *pchan = BKE_pose_channel_active(ob);
if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
@@ -1788,9 +1794,10 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
else {
/* object mode */
- Scene *scene = t->scene;
- Object *ob = OBACT;
- if (ob && (!select_only || (ob->flag & SELECT))) {
+ SceneLayer *sl = t->sl;
+ Object *ob = OBACT_NEW;
+ Base *base = BASACT_NEW;
+ if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
copy_v3_v3(r_center, ob->obmat[3]);
ok = true;
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index c730afe9e60..efc5517f3e5 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -688,10 +688,10 @@ static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const
int getLocalTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around)
{
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
Base *base;
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
int result = ORIENTATION_NONE;
const bool activeOnly = (around == V3D_AROUND_ACTIVE);
@@ -1118,16 +1118,16 @@ int getLocalTransformOrientation_ex(const bContext *C, float normal[3], float pl
}
else {
/* we need the one selected object, if its not active */
- View3D *v3d = CTX_wm_view3d(C);
- ob = OBACT;
- if (ob && (ob->flag & SELECT)) {
+ base = BASACT_NEW;
+ ob = OBACT_NEW;
+ if (base && ((base->flag & BASE_SELECTED) != 0)) {
/* pass */
}
else {
/* first selected */
ob = NULL;
- for (base = scene->base.first; base; base = base->next) {
- if (TESTBASELIB(v3d, base)) {
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if (TESTBASELIB_NEW(base)) {
ob = base->object;
break;
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index f8bb124e943..bd640463da2 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -49,7 +49,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BIF_gl.h"
+#include "GPU_immediate.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
@@ -163,36 +163,42 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
invert_m4_m4(imat, rv3d->viewmat);
-
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
for (p = t->tsnap.points.first; p; p = p->next) {
if (p == t->tsnap.selectedPoint) {
- glColor4ubv(selectedCol);
+ immUniformColor4ubv(selectedCol);
}
else {
- glColor4ubv(col);
+ immUniformColor4ubv(col);
}
- drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat);
+ imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos);
}
if (t->tsnap.status & POINT_INIT) {
- glColor4ubv(activeCol);
+ immUniformColor4ubv(activeCol);
- drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat);
+ imm_drawcircball(t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos);
}
/* draw normal if needed */
if (usingSnappingNormal(t) && validSnappingNormal(t)) {
- glColor4ubv(activeCol);
+ immUniformColor4ubv(activeCol);
- glBegin(GL_LINES);
- glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
- glVertex3f(t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
- t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
- t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
+ immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
+ t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
+ t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
+ immEnd();
}
-
+
+ immUnbindProgram();
+
if (v3d->zbuf)
glEnable(GL_DEPTH_TEST);
}
@@ -241,23 +247,29 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
glEnable(GL_BLEND);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
for (p = t->tsnap.points.first; p; p = p->next) {
if (p == t->tsnap.selectedPoint) {
- glColor4ubv(selectedCol);
+ immUniformColor4ubv(selectedCol);
}
else {
- glColor4ubv(col);
+ immUniformColor4ubv(col);
}
- ED_node_draw_snap(&ar->v2d, p->co, size, 0);
+ ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos);
}
if (t->tsnap.status & POINT_INIT) {
- glColor4ubv(activeCol);
+ immUniformColor4ubv(activeCol);
- ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder);
+ ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos);
}
-
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
}
@@ -520,7 +532,7 @@ static void initSnappingMode(TransInfo *t)
ToolSettings *ts = t->settings;
Object *obedit = t->obedit;
Scene *scene = t->scene;
- Base *base_act = scene->basact;
+ BaseLegacy *base_act = scene->basact;
if (t->spacetype == SPACE_NODE) {
/* force project off when not supported */
@@ -569,7 +581,9 @@ static void initSnappingMode(TransInfo *t)
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
(obedit == NULL) ) // Object Mode
{
- t->tsnap.modeSelect = SNAP_NOT_SELECTED;
+ /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
+ * TODO: perform self snap in gpencil_strokes */
+ t->tsnap.modeSelect = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_ALL : SNAP_NOT_SELECTED;
}
else {
/* Grid if snap is not possible */
@@ -599,7 +613,7 @@ static void initSnappingMode(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->tsnap.object_context == NULL) {
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- G.main, t->scene, SNAP_OBJECT_USE_CACHE,
+ G.main, t->scene, 0,
t->ar, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
@@ -1214,7 +1228,7 @@ bool snapObjectsTransform(
t->tsnap.object_context,
t->scene->toolsettings->snap_mode,
&(const struct SnapObjectParams){
- .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect,
+ .snap_select = t->tsnap.modeSelect,
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
},
mval, dist_px, NULL,
@@ -1304,7 +1318,7 @@ bool peelObjectsTransform(
t->tsnap.object_context,
mval,
&(const struct SnapObjectParams){
- .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect,
+ .snap_select = t->tsnap.modeSelect,
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
},
use_peel_object,
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 02900d7022c..2e95b67d508 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -59,6 +59,24 @@
#include "transform.h"
+enum eViewProj {
+ VIEW_PROJ_NONE = -1,
+ VIEW_PROJ_ORTHO = 0,
+ VIEW_PROJ_PERSP = -1,
+};
+
+typedef struct SnapData {
+ short snap_to;
+ float mval[2];
+ float ray_origin[3];
+ float ray_start[3];
+ float ray_dir[3];
+ float pmat[4][4]; /* perspective matrix */
+ float win_half[2];/* win x and y */
+ enum eViewProj view_proj;
+ float depth_range[2];
+} SnapData;
+
typedef struct SnapObjectData {
enum {
SNAP_MESH = 1,
@@ -110,12 +128,6 @@ struct SnapObjectContext {
};
-enum eViewProj {
- VIEW_PROJ_NONE = -1,
- VIEW_PROJ_ORTHO = 0,
- VIEW_PROJ_PERSP = -1,
-};
-
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
@@ -223,200 +235,87 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
/** \Common utilities
* \{ */
-
-/**
- * Struct that kepts basic information about a BVHTree build from a editmesh.
- */
-typedef struct BVHTreeFromMeshType {
- void *userdata;
- char type;
-} BVHTreeFromMeshType;
-
-typedef struct PreDefProject {
- float pmat[4][4]; /* perspective matrix multiplied by object matrix */
- float win_half[2];
- float dist_px_sq;
-} PreDefProject;
-
-static void precalc_project(
- PreDefProject *projectdefs, const ARegion *ar,
- const float dist_px, float obmat[4][4])
-{
- float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat;
- if (obmat) {
- mul_m4_m4m4(projectdefs->pmat, pmat, obmat);
- }
- else {
- copy_m4_m4(projectdefs->pmat, pmat);
- }
- projectdefs->win_half[0] = ar->winx / 2;
- projectdefs->win_half[1] = ar->winy / 2;
- projectdefs->dist_px_sq = SQUARE(dist_px);
-}
-
/**
- * From a threshold (maximum distance to snap in pixels) returns:
+ * Generates a struct with the immutable parameters that will be used on all objects.
*
- * - The *real* distance (3D) if you are in orthographic-view.
- * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
+ * \param snap_to: Element to snap, Vertice, Edge or Face.
+ * \param view_proj: ORTHO or PERSP.
+ * Currently only works one at a time, but can eventually operate as flag.
+ *
+ * \param mval: Mouse coords.
+ * (When NULL, ray-casting is handled without any projection matrix correction.)
+ * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
+ * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
+ * \param ray_direction: Unit length direction of the ray.
+ * \param depth_range: distances of clipe plane min and clip plane max;
*/
-static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
+static void snap_data_set(
+ SnapData *snapdata,
+ const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
+ const float mval[2], const float ray_origin[3], const float ray_start[3],
+ const float ray_direction[3], const float depth_range[2])
{
- const RegionView3D *rv3d = ar->regiondata;
- if (ar->winx >= ar->winy)
- return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
- else
- return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
+ if (ar) {
+ copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
+ snapdata->win_half[0] = ar->winx / 2;
+ snapdata->win_half[1] = ar->winy / 2;
+ }
+ if (mval) {
+ copy_v2_v2(snapdata->mval, mval);
+ }
+ snapdata->snap_to = snap_to;
+ copy_v3_v3(snapdata->ray_origin, ray_origin);
+ copy_v3_v3(snapdata->ray_start, ray_start);
+ copy_v3_v3(snapdata->ray_dir, ray_direction);
+ snapdata->view_proj = view_proj;
+ copy_v2_v2(snapdata->depth_range, depth_range);
}
-static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index)
+MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
{
- switch (meshdata->type) {
- case SNAP_MESH:
- {
- BVHTreeFromMesh *data = meshdata->userdata;
- const MVert *vert = data->vert;
- return vert[index].co;
- }
- case SNAP_EDIT_MESH:
- {
- BVHTreeFromEditMesh *data = meshdata->userdata;
- BMVert *eve = BM_vert_at_index(data->em->bm, index);
- return eve->co;
- }
- }
- return NULL;
+ float dvec[3];
+ sub_v3_v3v3(dvec, co, ray_start);
+ return dot_v3v3(dvec, ray_dir);
}
-static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3])
+static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data)
{
- switch (meshdata->type) {
- case SNAP_MESH:
- {
- BVHTreeFromMesh *data = meshdata->userdata;
- const MVert *vert = data->vert + index;
- normal_short_to_float_v3(r_no, vert->no);
- break;
- }
- case SNAP_EDIT_MESH:
- {
- BVHTreeFromEditMesh *data = meshdata->userdata;
- BMVert *eve = BM_vert_at_index(data->em->bm, index);
- copy_v3_v3(r_no, eve->no);
- break;
- }
- }
+ const MVert *vert = data->vert + index;
+
+ normal_short_to_float_v3(r_no, vert->no);
}
-static void get_edge_verts(
- const BVHTreeFromMeshType *meshdata, const int index,
- const float *v_pair[2])
+static void copy_bvert_no(const int index, float r_no[3], const BVHTreeFromEditMesh *data)
{
- switch (meshdata->type) {
- case SNAP_MESH:
- {
- BVHTreeFromMesh *data = meshdata->userdata;
-
- const MVert *vert = data->vert;
- const MEdge *edge = data->edge + index;
+ BMVert *eve = BM_vert_at_index(data->em->bm, index);
- v_pair[0] = vert[edge->v1].co;
- v_pair[1] = vert[edge->v2].co;
- break;
- }
- case SNAP_EDIT_MESH:
- {
- BVHTreeFromEditMesh *data = meshdata->userdata;
- BMEdge *eed = BM_edge_at_index(data->em->bm, index);
-
- v_pair[0] = eed->v1->co;
- v_pair[1] = eed->v2->co;
- break;
- }
- }
+ copy_v3_v3(r_no, eve->no);
}
-#define V3_MUL_ELEM(a, b) \
- (a)[0] * (b)[0], \
- (a)[1] * (b)[1], \
- (a)[2] * (b)[2]
-
-static bool test_vert_dist(
- const float vco[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3],
- /* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
- /* return args */
- float r_co[3])
+static void get_dm_edge_verts(const int index, const float *v_pair[2], const BVHTreeFromMesh *data)
{
- const float vco_sc[3] = {V3_MUL_ELEM(vco, scale)};
- const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
- const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
-
- float depth, dist_sq;
- dist_sq = dist_squared_to_ray_v3(origin_sc, dir_sc, vco_sc, &depth);
-
- if (depth < ray_depth_range[0]) {
- return false;
- }
-
- if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
- *dist_to_ray_sq = dist_sq;
-
- copy_v3_v3(r_co, vco);
+ const MVert *vert = data->vert;
+ const MEdge *edge = data->edge + index;
- *ray_depth = depth;
- return true;
- }
- return false;
+ v_pair[0] = vert[edge->v1].co;
+ v_pair[1] = vert[edge->v2].co;
}
-static bool test_edge_dist(
- const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3],
- /* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
- /* return args */
- float r_co[3])
+static void get_bedge_verts(const int index, const float *v_pair[2], const BVHTreeFromEditMesh *data)
{
- const float v1_sc[3] = {V3_MUL_ELEM(v1, scale)};
- const float v2_sc[3] = {V3_MUL_ELEM(v2, scale)};
- const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
- const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
-
- float tmp_co[3], depth, dist_sq;
- dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
+ BMEdge *eed = BM_edge_at_index(data->em->bm, index);
- if (depth < ray_depth_range[0]) {
- return false;
- }
-
- if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
- *dist_to_ray_sq = dist_sq;
-
- tmp_co[0] /= scale[0];
- tmp_co[1] /= scale[1];
- tmp_co[2] /= scale[2];
-
- copy_v3_v3(r_co, tmp_co);
-
- *ray_depth = depth;
- return true;
- }
- return false;
+ v_pair[0] = eed->v1->co;
+ v_pair[1] = eed->v2->co;
}
-#undef V3_MUL_ELEM
-
static bool test_projected_vert_dist(
- PreDefProject *projectdefs,
- const float co[3], const enum eViewProj view_proj,
- const float mval[2], const float depth_range[2],
- float r_co[3])
+ const float depth_range[2], const float mval[2], const float co[3],
+ float pmat[4][4], const float win_half[2], const bool is_persp,
+ float *dist_px_sq, float r_co[3])
{
float depth;
- float(*pmat)[4] = projectdefs->pmat;
- if (view_proj == VIEW_PROJ_PERSP) {
+ if (is_persp) {
depth = mul_project_m4_v3_zfac(pmat, co);
if (depth < depth_range[0] || depth > depth_range[1]) {
return false;
@@ -428,109 +327,106 @@ static bool test_projected_vert_dist(
(dot_m4_v3_row_y(pmat, co) + pmat[3][1]),
};
- if (view_proj == VIEW_PROJ_PERSP) {
+ if (is_persp) {
mul_v2_fl(co2d, 1 / depth);
}
co2d[0] += 1.0f;
co2d[1] += 1.0f;
- co2d[0] *= projectdefs->win_half[0];
- co2d[1] *= projectdefs->win_half[1];
+ co2d[0] *= win_half[0];
+ co2d[1] *= win_half[1];
const float dist_sq = len_squared_v2v2(mval, co2d);
- if (dist_sq < projectdefs->dist_px_sq) {
+ if (dist_sq < *dist_px_sq) {
copy_v3_v3(r_co, co);
- projectdefs->dist_px_sq = dist_sq;
+ *dist_px_sq = dist_sq;
return true;
}
return false;
}
static bool test_projected_edge_dist(
- PreDefProject *projectdefs,
- const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3],
- const enum eViewProj view_proj, const float mval[2], const float depth_range[2],
- float r_co[3])
+ const float depth_range[2], const float mval[2],
+ float pmat[4][4], const float win_half[2], const bool is_persp,
+ const float ray_start[3], const float ray_dir[3],
+ const float va[3], const float vb[3],
+ float *dist_px_sq, float r_co[3])
{
float tmp_co[3], depth;
- dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth);
- return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co);
+ dist_squared_ray_to_seg_v3(ray_start, ray_dir, va, vb, tmp_co, &depth);
+ return test_projected_vert_dist(depth_range, mval, tmp_co, pmat, win_half, is_persp, dist_px_sq, r_co);
}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \Walk DFS
- * \{ */
-typedef struct Object_Nearest2dPrecalc {
+typedef struct Nearest2dPrecalc {
float ray_origin_local[3];
float ray_direction_local[3];
float ray_inv_dir[3];
- PreDefProject projectdefs;
+ float ray_min_dist;
+ float pmat[4][4]; /* perspective matrix multiplied by object matrix */
+ bool is_persp;
+ float win_half[2];
+
float mval[2];
bool sign[3];
- bool r_axis_closest[3];
- float depth_range[2];
-
- void *userdata;
- int index;
- float co[3];
- float no[3];
-} Object_Nearest2dPrecalc;
+} Nearest2dPrecalc;
-
-static void nearest2d_precalc(
- Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar,
- const float dist_px, float obmat[4][4],
- const float ray_origin_local[3], const float ray_direction_local[3],
- const float mval[2], const float depth_range[2])
+/**
+ * \param lpmat: Perspective matrix multiplied by object matrix
+ */
+static void dist_squared_to_projected_aabb_precalc(
+ struct Nearest2dPrecalc *neasrest_precalc,
+ float lpmat[4][4], bool is_persp, const float win_half[2],
+ const float ray_min_dist, const float mval[2],
+ const float ray_origin_local[3], const float ray_direction_local[3])
{
- precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat);
+ copy_m4_m4(neasrest_precalc->pmat, lpmat);
+ neasrest_precalc->is_persp = is_persp;
+ copy_v2_v2(neasrest_precalc->win_half, win_half);
+ neasrest_precalc->ray_min_dist = ray_min_dist;
+
copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local);
copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local);
copy_v2_v2(neasrest_precalc->mval, mval);
- copy_v2_v2(neasrest_precalc->depth_range, depth_range);
for (int i = 0; i < 3; i++) {
- neasrest_precalc->ray_inv_dir[i] =
+ neasrest_precalc->ray_inv_dir[i] =
(neasrest_precalc->ray_direction_local[i] != 0.0f) ?
(1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX;
neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f);
- neasrest_precalc->r_axis_closest[i] = true;
}
}
-static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
+/* Returns the distance from a 2d coordinate to a BoundBox (Projected) */
+static float dist_squared_to_projected_aabb(
+ struct Nearest2dPrecalc *data,
+ const float bbmin[3], const float bbmax[3],
+ bool r_axis_closest[3])
{
- Object_Nearest2dPrecalc *data = user_data;
float local_bvmin[3], local_bvmax[3];
if (data->sign[0]) {
- local_bvmin[0] = bounds[0].max;
- local_bvmax[0] = bounds[0].min;
+ local_bvmin[0] = bbmax[0];
+ local_bvmax[0] = bbmin[0];
}
else {
- local_bvmin[0] = bounds[0].min;
- local_bvmax[0] = bounds[0].max;
+ local_bvmin[0] = bbmin[0];
+ local_bvmax[0] = bbmax[0];
}
if (data->sign[1]) {
- local_bvmin[1] = bounds[1].max;
- local_bvmax[1] = bounds[1].min;
+ local_bvmin[1] = bbmax[1];
+ local_bvmax[1] = bbmin[1];
}
else {
- local_bvmin[1] = bounds[1].min;
- local_bvmax[1] = bounds[1].max;
+ local_bvmin[1] = bbmin[1];
+ local_bvmax[1] = bbmax[1];
}
if (data->sign[2]) {
- local_bvmin[2] = bounds[2].max;
- local_bvmax[2] = bounds[2].min;
+ local_bvmin[2] = bbmax[2];
+ local_bvmax[2] = bbmin[2];
}
else {
- local_bvmin[2] = bounds[2].min;
- local_bvmax[2] = bounds[2].max;
+ local_bvmin[2] = bbmin[2];
+ local_bvmax[2] = bbmax[2];
}
const float tmin[3] = {
@@ -543,7 +439,9 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
(local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1],
(local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2],
};
+ /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */
float va[3], vb[3];
+ /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */
float rtmin, rtmax;
int main_axis;
@@ -551,38 +449,38 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
rtmax = tmax[0];
va[0] = vb[0] = local_bvmax[0];
main_axis = 3;
- data->r_axis_closest[0] = data->sign[0];
+ r_axis_closest[0] = data->sign[0];
}
else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
rtmax = tmax[1];
va[1] = vb[1] = local_bvmax[1];
main_axis = 2;
- data->r_axis_closest[1] = data->sign[1];
+ r_axis_closest[1] = data->sign[1];
}
else {
rtmax = tmax[2];
va[2] = vb[2] = local_bvmax[2];
main_axis = 1;
- data->r_axis_closest[2] = data->sign[2];
+ r_axis_closest[2] = data->sign[2];
}
if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
rtmin = tmin[0];
va[0] = vb[0] = local_bvmin[0];
main_axis -= 3;
- data->r_axis_closest[0] = !data->sign[0];
+ r_axis_closest[0] = !data->sign[0];
}
else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
rtmin = tmin[1];
va[1] = vb[1] = local_bvmin[1];
main_axis -= 1;
- data->r_axis_closest[1] = !data->sign[1];
+ r_axis_closest[1] = !data->sign[1];
}
else {
rtmin = tmin[2];
va[2] = vb[2] = local_bvmin[2];
main_axis -= 2;
- data->r_axis_closest[2] = !data->sign[2];
+ r_axis_closest[2] = !data->sign[2];
}
if (main_axis < 0) {
main_axis += 3;
@@ -590,22 +488,34 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
/* if rtmin < rtmax, ray intersect `AABB` */
if (rtmin <= rtmax) {
+#define IGNORE_BEHIND_RAY
#ifdef IGNORE_BEHIND_RAY
- /* `if rtmax < depth_min`, the whole `AABB` is behind us */
- if (rtmax < min_depth) {
- return fallback;
+ /* `if rtmax < depth_min`, the hit is behind us */
+ if (rtmax < data->ray_min_dist) {
+ /* Test if the entire AABB is behind us */
+ float depth = depth_get(
+ local_bvmax, data->ray_origin_local, data->ray_direction_local);
+ if (depth < (data->ray_min_dist)) {
+ return FLT_MAX;
+ }
}
#endif
const float proj = rtmin * data->ray_direction_local[main_axis];
- data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj);
- return true;
+ r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj);
+ return 0.0f;
}
#ifdef IGNORE_BEHIND_RAY
- /* `if rtmin < depth_min`, the whole `AABB` is behing us */
- else if (rtmin < min_depth) {
- return fallback;
+ /* `if rtmin < depth_min`, the hit is behing us */
+ else if (rtmin < data->ray_min_dist) {
+ /* Test if the entire AABB is behind us */
+ float depth = depth_get(
+ local_bvmax, data->ray_origin_local, data->ray_direction_local);
+ if (depth < (data->ray_min_dist)) {
+ return FLT_MAX;
+ }
}
#endif
+#undef IGNORE_BEHIND_RAY
if (data->sign[main_axis]) {
va[main_axis] = local_bvmax[main_axis];
vb[main_axis] = local_bvmin[main_axis];
@@ -616,31 +526,35 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
}
float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]);
- float (*pmat)[4] = data->projectdefs.pmat;
- float depth_a = mul_project_m4_v3_zfac(pmat, va);
- float depth_b = depth_a + pmat[main_axis][3] * scale;
+ float (*pmat)[4] = data->pmat;
float va2d[2] = {
(dot_m4_v3_row_x(pmat, va) + pmat[3][0]),
(dot_m4_v3_row_y(pmat, va) + pmat[3][1]),
};
float vb2d[2] = {
- (va2d[0] + pmat[main_axis][0] * scale) / depth_b,
- (va2d[1] + pmat[main_axis][1] * scale) / depth_b,
+ (va2d[0] + pmat[main_axis][0] * scale),
+ (va2d[1] + pmat[main_axis][1] * scale),
};
- va2d[0] /= depth_a;
- va2d[1] /= depth_a;
+ if (data->is_persp) {
+ float depth_a = mul_project_m4_v3_zfac(pmat, va);
+ float depth_b = depth_a + pmat[main_axis][3] * scale;
+ va2d[0] /= depth_a;
+ va2d[1] /= depth_a;
+ vb2d[0] /= depth_b;
+ vb2d[1] /= depth_b;
+ }
va2d[0] += 1.0f;
va2d[1] += 1.0f;
vb2d[0] += 1.0f;
vb2d[1] += 1.0f;
- va2d[0] *= data->projectdefs.win_half[0];
- va2d[1] *= data->projectdefs.win_half[1];
- vb2d[0] *= data->projectdefs.win_half[0];
- vb2d[1] *= data->projectdefs.win_half[1];
+ va2d[0] *= data->win_half[0];
+ va2d[1] *= data->win_half[1];
+ vb2d[0] *= data->win_half[0];
+ vb2d[1] *= data->win_half[1];
//float dvec[2], edge[2], rdist;
//sub_v2_v2v2(dvec, data->mval, va2d);
@@ -653,73 +567,146 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
lambda /= edge[0] * edge[0] + edge[1] * edge[1];
if (lambda <= 0.0f) {
rdist = len_squared_v2v2(data->mval, va2d);
- data->r_axis_closest[main_axis] = true;
+ r_axis_closest[main_axis] = true;
}
else if (lambda >= 1.0f) {
rdist = len_squared_v2v2(data->mval, vb2d);
- data->r_axis_closest[main_axis] = false;
+ r_axis_closest[main_axis] = false;
}
else {
va2d[0] += edge[0] * lambda;
va2d[1] += edge[1] * lambda;
rdist = len_squared_v2v2(data->mval, va2d);
- data->r_axis_closest[main_axis] = lambda < 0.5f;
+ r_axis_closest[main_axis] = lambda < 0.5f;
}
}
else {
rdist = len_squared_v2v2(data->mval, va2d);
}
- return rdist < data->projectdefs.dist_px_sq;
+ return rdist;
+}
+
+static float dist_squared_to_projected_aabb_simple(
+ float lpmat[4][4], const float win_half[2],
+ const float ray_min_dist, const float mval[2],
+ const float ray_origin_local[3], const float ray_direction_local[3],
+ const float bbmin[3], const float bbmax[3])
+{
+ struct Nearest2dPrecalc data;
+ dist_squared_to_projected_aabb_precalc(
+ &data, lpmat, true, win_half, ray_min_dist,
+ mval, ray_origin_local, ray_direction_local);
+
+ bool dummy[3] = {true, true, true};
+ return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy);
+}
+
+static float dist_aabb_to_plane(
+ const float bbmin[3], const float bbmax[3],
+ const float plane_co[3], const float plane_no[3])
+{
+ const float local_bvmin[3] = {
+ (plane_no[0] < 0) ? bbmax[0] : bbmin[0],
+ (plane_no[1] < 0) ? bbmax[1] : bbmin[1],
+ (plane_no[2] < 0) ? bbmax[2] : bbmin[2],
+ };
+ return depth_get(local_bvmin, plane_co, plane_no);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \Walk DFS
+ * \{ */
+
+typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data);
+typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
+
+typedef struct Nearest2dUserData {
+ struct Nearest2dPrecalc data_precalc;
+
+ float dist_px_sq;
+
+ bool r_axis_closest[3];
+
+ float depth_range[2];
+
+ void *userdata;
+ Nearest2DGetEdgeVertsCallback get_edge_verts;
+ Nearest2DCopyVertNoCallback copy_vert_no;
+
+ int index;
+ float co[3];
+ float no[3];
+} Nearest2dUserData;
+
+
+static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
+{
+ Nearest2dUserData *data = user_data;
+ const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min};
+ const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max};
+ const float rdist = dist_squared_to_projected_aabb(
+ &data->data_precalc, bbmin, bbmax, data->r_axis_closest);
+ return rdist < data->dist_px_sq;
}
static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata)
{
- struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+ struct Nearest2dUserData *data = userdata;
+ struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc;
const float co[3] = {
(bounds[0].min + bounds[0].max) / 2,
(bounds[1].min + bounds[1].max) / 2,
(bounds[2].min + bounds[2].max) / 2,
};
- /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
- * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
- * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
if (test_projected_vert_dist(
- &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP,
- neasrest_precalc->mval, neasrest_precalc->depth_range,
- neasrest_precalc->co))
+ data->depth_range,
+ neasrest_precalc->mval, co,
+ neasrest_precalc->pmat,
+ neasrest_precalc->win_half,
+ neasrest_precalc->is_persp,
+ &data->dist_px_sq,
+ data->co))
{
- copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no);
- neasrest_precalc->index = index;
+ data->copy_vert_no(index, data->no, data->userdata);
+ data->index = index;
}
return true;
}
static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
{
- struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+ struct Nearest2dUserData *data = userdata;
+ struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc;
const float *v_pair[2];
- get_edge_verts(neasrest_precalc->userdata, index, v_pair);
+ data->get_edge_verts(index, v_pair, data->userdata);
- /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
- * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
- * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
if (test_projected_edge_dist(
- &neasrest_precalc->projectdefs, v_pair[0], v_pair[1],
- neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local,
- VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range,
- neasrest_precalc->co))
+ data->depth_range,
+ neasrest_precalc->mval,
+ neasrest_precalc->pmat,
+ neasrest_precalc->win_half,
+ neasrest_precalc->is_persp,
+ neasrest_precalc->ray_origin_local,
+ neasrest_precalc->ray_direction_local,
+ v_pair[0], v_pair[1],
+ &data->dist_px_sq,
+ data->co))
{
- sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]);
- neasrest_precalc->index = index;
+ sub_v3_v3v3(data->no, v_pair[0], v_pair[1]);
+ data->index = index;
}
return true;
}
static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata)
{
- const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest;
+ const bool *r_axis_closest = ((struct Nearest2dUserData *)userdata)->r_axis_closest;
return r_axis_closest[axis];
}
@@ -731,46 +718,56 @@ static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char a
* \{ */
static bool snapArmature(
- const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
- const short snap_to, const float origin[3], const float dir[3],
- const float mval[2], const enum eViewProj view_proj, const float depth_range[2],
+ SnapData *snapdata,
+ Object *ob, bArmature *arm, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
bool retval = false;
- float ray_start_local[3], ray_normal_local[3];
- if (snap_to != SCE_SNAP_MODE_VERTEX) {
+ float ray_start_local[3], ray_normal_local[3]; /* Used only in the snap to edges */
+ if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
float imat[4][4];
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, origin);
- copy_v3_v3(ray_normal_local, dir);
+ copy_v3_v3(ray_start_local, snapdata->ray_origin);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
}
+ else if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { /* Currently only edge and vert */
+ return retval;
+ }
- PreDefProject projectdefs;
- precalc_project(&projectdefs, ar, *dist_px, obmat);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float lpmat[4][4], dist_px_sq;
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_px_sq = SQUARE(*dist_px);
if (arm->edbo) {
for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
if (eBone->layer & arm->layer) {
/* skip hidden or moving (selected) bones */
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
- &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, eBone->head,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
retval |= test_projected_vert_dist(
- &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, eBone->tail,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
- &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local,
- view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, lpmat,
+ snapdata->win_half, is_persp, ray_start_local, ray_normal_local,
+ eBone->head, eBone->tail,
+ &dist_px_sq, r_loc);
break;
}
}
@@ -785,52 +782,60 @@ static bool snapArmature(
const float *head_vec = pchan->pose_head;
const float *tail_vec = pchan->pose_tail;
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
- &projectdefs, head_vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, head_vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
retval |= test_projected_vert_dist(
- &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, tail_vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
- &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local,
- view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, lpmat,
+ snapdata->win_half, is_persp, ray_start_local, ray_normal_local,
+ head_vec, tail_vec,
+ &dist_px_sq, r_loc);
break;
}
}
}
}
if (retval) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ *dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
return true;
}
return false;
}
static bool snapCurve(
- const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float depth_range[2],
+ SnapData *snapdata,
+ Object *ob, Curve *cu, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
bool retval = false;
/* only vertex snapping mode (eg control points and handles) supported for now) */
- if (snap_to != SCE_SNAP_MODE_VERTEX) {
+ if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) {
return retval;
}
- PreDefProject projectdefs;
- precalc_project(&projectdefs, ar, *dist_px, obmat);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float lpmat[4][4], dist_px_sq;
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_px_sq = SQUARE(*dist_px);
for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
for (int u = 0; u < nu->pntsu; u++) {
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
if (ob->mode == OB_MODE_EDIT) {
@@ -840,19 +845,25 @@ static bool snapCurve(
break;
}
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
/* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
if (!(nu->bezt[u].f1 & SELECT) &&
!(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
{
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[0],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
if (!(nu->bezt[u].f3 & SELECT) &&
!(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
{
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[2],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
else {
@@ -861,7 +872,9 @@ static bool snapCurve(
break;
}
retval |= test_projected_vert_dist(
- &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bp[u].vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
else {
@@ -869,11 +882,15 @@ static bool snapCurve(
if (nu->pntsu > 1) {
if (nu->bezt) {
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
else {
retval |= test_projected_vert_dist(
- &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bp[u].vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
}
@@ -885,8 +902,9 @@ static bool snapCurve(
}
}
if (retval) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ *dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
return true;
}
return false;
@@ -894,11 +912,10 @@ static bool snapCurve(
/* may extend later (for now just snaps to empty center) */
static bool snapEmpty(
- const ARegion *ar, Object *ob, float obmat[4][4],
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float depth_range[2],
+ SnapData *snapdata,
+ Object *ob, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
@@ -909,15 +926,19 @@ static bool snapEmpty(
}
/* for now only vertex supported */
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
- PreDefProject projectdefs;
- precalc_project(&projectdefs, ar, *dist_px, NULL);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
float tmp_co[3];
copy_v3_v3(tmp_co, obmat[3]);
- if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ if (test_projected_vert_dist(
+ snapdata->depth_range, snapdata->mval, tmp_co,
+ snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc)) {
+ *dist_px = sqrtf(dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
}
break;
@@ -930,18 +951,17 @@ static bool snapEmpty(
}
static bool snapCamera(
- const SnapObjectContext *sctx, Object *object, float obmat[4][4],
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float depth_range[2],
+ const SnapObjectContext *sctx, SnapData *snapdata,
+ Object *object, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
Scene *scene = sctx->scene;
- PreDefProject projectdefs;
- precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
bool retval = false;
@@ -962,7 +982,7 @@ static bool snapCamera(
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
MovieTrackingObject *tracking_object;
@@ -1002,7 +1022,9 @@ static bool snapCamera(
mul_m4_v3(vertex_obmat, bundle_pos);
retval |= test_projected_vert_dist(
- &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, bundle_pos,
+ snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
@@ -1013,7 +1035,8 @@ static bool snapCamera(
}
if (retval) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ *dist_px = sqrtf(dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
return true;
}
return false;
@@ -1025,57 +1048,10 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
}
-struct NearestDM_Data {
- void *bvhdata;
- const float *depth_range;
- float *ray_depth;
-};
-
-static void test_vert_ray_dist_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- const struct BVHTreeFromMeshType *data = ndata->bvhdata;
-
- const float *co = get_vert_co(data, index);
-
- if (test_vert_dist(
- co, origin, dir, ndata->depth_range,
- scale, ndata->ray_depth, &nearest->dist_sq,
- nearest->co))
- {
- copy_vert_no(data, index, nearest->no);
- nearest->index = index;
- }
-}
-
-static void test_edge_ray_dist_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- BVHTreeFromMeshType *data = ndata->bvhdata;
-
- const float *v_pair[2];
- get_edge_verts(data, index, v_pair);
-
- if (test_edge_dist(
- v_pair[0], v_pair[1], origin, dir, ndata->depth_range,
- scale, ndata->ray_depth, &nearest->dist_sq,
- nearest->co))
- {
- sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
- nearest->index = index;
- }
-}
-
static bool snapDerivedMesh(
- SnapObjectContext *sctx,
+ SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
+ bool do_bb,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1084,12 +1060,12 @@ static bool snapDerivedMesh(
{
bool retval = false;
- if (snap_to == SCE_SNAP_MODE_FACE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
if (dm->getNumPolys(dm) == 0) {
return retval;
}
}
- else if (snap_to == SCE_SNAP_MODE_EDGE) {
+ else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (dm->getNumEdges(dm) == 0) {
return retval;
}
@@ -1100,289 +1076,259 @@ static bool snapDerivedMesh(
}
}
- {
- bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO);
+ bool need_ray_start_correction_init =
+ (snapdata->snap_to == SCE_SNAP_MODE_FACE) &&
+ (snapdata->view_proj == VIEW_PROJ_ORTHO);
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff;
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff;
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
+ copy_v3_v3(ray_start_local, snapdata->ray_start);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
- /* local scale in normal direction */
- local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
- if (do_bb) {
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ float lpmat[4][4];
+ float ray_org_local[3];
+ float ray_min_dist;
+ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ ray_min_dist = snapdata->depth_range[0] * local_scale;
+ }
- if (bb) {
- BoundBox bb_temp;
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
- /* We cannot afford a bounding box with some null dimension, which may happen in some cases...
- * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
- bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
+ if (do_bb) {
+ BoundBox *bb = BKE_object_boundbox_get(ob);
- /* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'dist_px'),
- * scale up so we can snap against verts & edges on the boundbox, see T46816. */
- if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f);
- bb = &bb_temp;
- }
+ if (bb) {
+ BoundBox bb_temp;
- /* was local_depth, see: T47838 */
- len_diff = BVH_RAYCAST_DIST_MAX;
+ /* We cannot afford a bounding box with some null dimension, which may happen in some cases...
+ * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
+ bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
- if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */
+ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ float dist_px_sq = dist_squared_to_projected_aabb_simple(
+ lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
+ ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
+ if (dist_px_sq > SQUARE(*dist_px))
+ {
return retval;
}
- need_ray_start_correction_init = false;
- }
- }
-
- SnapObjectData_Mesh *sod = NULL;
- BVHTreeFromMesh *treedata = NULL, treedata_stack;
-
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- sod = *sod_p;
}
else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
- }
-
- int tree_index = -1;
- switch (snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
- case SCE_SNAP_MODE_EDGE:
- tree_index = 1;
- break;
- case SCE_SNAP_MODE_VERTEX:
- tree_index = 0;
- break;
- }
- if (tree_index != -1) {
- if (sod->bvh_trees[tree_index] == NULL) {
- sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
- }
- treedata = sod->bvh_trees[tree_index];
-
- /* the tree is owned by the DM and may have been freed since we last used! */
- if (treedata && treedata->tree) {
- if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
- free_bvhtree_from_mesh(treedata);
- }
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
+ {
+ return retval;
}
}
+ /* was local_depth, see: T47838 */
+ len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
+ if (len_diff < 0) len_diff = 0.0f;
+ need_ray_start_correction_init = false;
}
- else {
- treedata = &treedata_stack;
- memset(treedata, 0, sizeof(*treedata));
+ }
+
+ SnapObjectData_Mesh *sod = NULL;
+ BVHTreeFromMesh *treedata = NULL;
+
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ }
+
+ int tree_index = -1;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ tree_index = 2;
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ tree_index = 1;
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ tree_index = 0;
+ break;
+ }
+ if (tree_index != -1) {
+ if (sod->bvh_trees[tree_index] == NULL) {
+ sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
}
+ treedata = sod->bvh_trees[tree_index];
- if (treedata && treedata->tree == NULL) {
- switch (snap_to) {
- case SCE_SNAP_MODE_FACE:
- bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
- break;
- case SCE_SNAP_MODE_EDGE:
- bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
- break;
- case SCE_SNAP_MODE_VERTEX:
- bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
- break;
+ /* the tree is owned by the DM and may have been freed since we last used! */
+ if (treedata && treedata->tree) {
+ if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
+ free_bvhtree_from_mesh(treedata);
}
}
+ }
- if (!treedata || !treedata->tree) {
- return retval;
+ if (treedata && treedata->tree == NULL) {
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
+ break;
}
+ }
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
- if (snap_to == SCE_SNAP_MODE_FACE) {
- /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
- * been *inside* boundbox, leading to snap failures (see T38409).
- * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
- */
- if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
- if (need_ray_start_correction_init) {
- /* We *need* a reasonably valid len_diff in this case.
- * Use BHVTree to find the closest face from ray_start_local.
- */
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
- if (nearest.index != -1) {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- }
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
+ * been *inside* boundbox, leading to snap failures (see T38409).
+ * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ */
+ if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
+ if (need_ray_start_correction_init) {
+ /* We *need* a reasonably valid len_diff in this case.
+ * Use BHVTree to find the closest face from ray_start_local.
+ */
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
+ if (nearest.index != -1) {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
}
- float ray_org_local[3];
-
- copy_v3_v3(ray_org_local, ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
- * away ray_start values (as returned in case of ortho view3d), see T38358.
+ }
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T38358.
*/
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale);
+ ray_start_local, ray_org_local, ray_normal_local,
+ len_diff + snapdata->depth_range[0] * local_scale);
local_depth -= len_diff;
}
- else {
- len_diff = 0.0f;
- }
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
-
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
- }
- }
- }
- }
+ else len_diff = 0.0f;
}
- /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
else {
- const ARegion *ar = sctx->v3d_data.ar;
-
- float ray_org_local[3];
- copy_v3_v3(ray_org_local, ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH};
-
- if (view_proj == VIEW_PROJ_PERSP) {
- Object_Nearest2dPrecalc neasrest_precalc;
- neasrest_precalc.userdata = &treedata_type;
- neasrest_precalc.index = -1;
-
- nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
- ray_org_local, ray_normal_local, mval, depth_range);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+ len_diff = 0.0f;
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
- if (neasrest_precalc.index != -1) {
- copy_v3_v3(r_loc, neasrest_precalc.co);
+ /* back to worldspace */
mul_m4_v3(obmat, r_loc);
+
if (r_no) {
- copy_v3_v3(r_no, neasrest_precalc.no);
+ copy_v3_v3(r_no, hit.no);
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
- *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
retval = true;
- }
- }
- else {
- BVHTreeNearest nearest;
-
- nearest.index = -1;
- float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
- nearest.dist_sq = SQUARE(dist_3d);
-
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
-
- struct NearestDM_Data userdata;
- userdata.bvhdata = &treedata_type;
- userdata.depth_range = depth_range;
- userdata.ray_depth = ray_depth;
-
- BVHTree_NearestToRayCallback cb_test_ray_dist =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_vert_ray_dist_cb : test_edge_ray_dist_cb;
-
- if (BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- true, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+ if (r_index) {
+ *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
}
- *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
-
- retval = true;
}
}
}
-
- if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
- if (treedata) {
- free_bvhtree_from_mesh(treedata);
+ }
+ /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
+ else {
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no,
+ .index = -1};
+
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
+
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+
+ retval = true;
}
}
@@ -1390,11 +1336,8 @@ static bool snapDerivedMesh(
}
static bool snapEditMesh(
- SnapObjectContext *sctx,
+ SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1403,12 +1346,12 @@ static bool snapEditMesh(
{
bool retval = false;
- if (snap_to == SCE_SNAP_MODE_FACE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
if (em->bm->totface == 0) {
return retval;
}
}
- if (snap_to == SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (em->bm->totedge == 0) {
return retval;
}
@@ -1419,292 +1362,246 @@ static bool snapEditMesh(
}
}
- {
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_normal_local[3];
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_normal_local[3];
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_normal_local, ray_normal);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
- SnapObjectData_EditMesh *sod = NULL;
+ /* local scale in normal direction */
+ float local_scale = normalize_v3(ray_normal_local);
+ float local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
- BVHTreeFromEditMesh *treedata = NULL, treedata_stack;
+ SnapObjectData_EditMesh *sod = NULL;
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- sod = *sod_p;
- }
- else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
- }
+ BVHTreeFromEditMesh *treedata = NULL;
- int tree_index = -1;
- switch (snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
- case SCE_SNAP_MODE_EDGE:
- tree_index = 1;
- break;
- case SCE_SNAP_MODE_VERTEX:
- tree_index = 0;
- break;
- }
- if (tree_index != -1) {
- if (sod->bvh_trees[tree_index] == NULL) {
- sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
- }
- treedata = sod->bvh_trees[tree_index];
- }
- }
- else {
- treedata = &treedata_stack;
- memset(treedata, 0, sizeof(*treedata));
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ }
+
+ int tree_index = -1;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ tree_index = 2;
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ tree_index = 1;
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ tree_index = 0;
+ break;
+ }
+ if (tree_index != -1) {
+ if (sod->bvh_trees[tree_index] == NULL) {
+ sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
}
+ treedata = sod->bvh_trees[tree_index];
+ }
- if (treedata && treedata->tree == NULL) {
- switch (snap_to) {
- case SCE_SNAP_MODE_FACE:
- {
- BLI_bitmap *looptri_mask = NULL;
- int looptri_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_face_fn) {
- looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- em->bm, looptri_mask,
- sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_looptri_ex(treedata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6, NULL);
- if (looptri_mask) {
- MEM_freeN(looptri_mask);
- }
- break;
+ if (treedata && treedata->tree == NULL) {
+ BLI_bitmap *elem_mask = NULL;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ {
+ int looptri_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_face_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ em->bm, elem_mask,
+ sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
}
- case SCE_SNAP_MODE_EDGE:
- {
- BLI_bitmap *edges_mask = NULL;
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, edges_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_edges_ex(treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6);
- if (edges_mask) {
- MEM_freeN(edges_mask);
- }
- break;
+ bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL);
+ break;
+ }
+ case SCE_SNAP_MODE_EDGE:
+ {
+ int edges_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_edge_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
+ edges_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_EDGES_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
+ sctx->callbacks.edit_mesh.user_data);
}
- case SCE_SNAP_MODE_VERTEX:
- {
- BLI_bitmap *verts_mask = NULL;
- int verts_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_vert_fn) {
- verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
- verts_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_VERTS_OF_MESH, em->bm, verts_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_verts_ex(treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6);
- if (verts_mask) {
- MEM_freeN(verts_mask);
- }
- break;
+ bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6);
+ break;
+ }
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ int verts_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_vert_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ verts_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_VERTS_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
+ sctx->callbacks.edit_mesh.user_data);
}
+ bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6);
+ break;
}
}
-
- if (!treedata || !treedata->tree) {
- return retval;
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
}
+ }
- if (snap_to == SCE_SNAP_MODE_FACE) {
- float ray_start_local[3];
- copy_v3_v3(ray_start_local, ray_start);
- mul_m4_v3(imat, ray_start_local);
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
- /* local scale in normal direction */
- float local_scale = normalize_v3(ray_normal_local);
- float local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
+ float ray_start_local[3];
+ copy_v3_v3(ray_start_local, snapdata->ray_start);
+ mul_m4_v3(imat, ray_start_local);
- /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
- * been *inside* boundbox, leading to snap failures (see T38409).
- * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start
+ * may already been *inside* boundbox, leading to snap failures (see T38409).
+ * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ */
+ float len_diff = 0.0f;
+ if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
+ /* We *need* a reasonably valid len_diff in this case.
+ * Use BHVTree to find the closest face from ray_start_local.
*/
- float len_diff = 0.0f;
- if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
- /* We *need* a reasonably valid len_diff in this case.
- * Use BHVTree to find the closest face from ray_start_local.
- */
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- if (BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
- {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ if (BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
+ {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
float ray_org_local[3];
- copy_v3_v3(ray_org_local, ray_origin);
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
/* We pass a temp ray_start, set from object's boundbox,
* to avoid precision issues with very far away ray_start values
* (as returned in case of ortho view3d), see T38358.
*/
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale);
+ ray_start_local, ray_org_local, ray_normal_local,
+ len_diff + snapdata->depth_range[0] * local_scale);
local_depth -= len_diff;
}
+ else len_diff = 0.0f;
}
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
-
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- *r_index = hit.index;
- }
- }
- }
- }
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
}
else {
- const ARegion *ar = sctx->v3d_data.ar;
-
- float ray_org_local[3];
- copy_v3_v3(ray_org_local, ray_origin);
- mul_m4_v3(imat, ray_org_local);
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH};
-
- if (view_proj == VIEW_PROJ_PERSP) {
- Object_Nearest2dPrecalc neasrest_precalc;
- neasrest_precalc.userdata = &treedata_type;
- neasrest_precalc.index = -1;
-
- nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
- ray_org_local, ray_normal_local, mval, depth_range);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
- if (neasrest_precalc.index != -1) {
- copy_v3_v3(r_loc, neasrest_precalc.co);
+ /* back to worldspace */
mul_m4_v3(obmat, r_loc);
+
if (r_no) {
- copy_v3_v3(r_no, neasrest_precalc.no);
+ copy_v3_v3(r_no, hit.no);
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
- *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
retval = true;
- }
- }
- else {
- BVHTreeNearest nearest;
-
- nearest.index = -1;
- float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
- nearest.dist_sq = SQUARE(dist_3d);
-
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
-
- struct NearestDM_Data userdata;
- userdata.bvhdata = &treedata_type;
- userdata.depth_range = depth_range;
- userdata.ray_depth = ray_depth;
-
- BVHTree_NearestToRayCallback cb_test_ray_dist =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_vert_ray_dist_cb : test_edge_ray_dist_cb;
-
- if (BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+ if (r_index) {
+ *r_index = hit.index;
}
- *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
-
- retval = true;
}
}
}
-
- if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
- if (treedata) {
- free_bvhtree_from_editmesh(treedata);
+ }
+ else {
+ float ray_org_local[3];
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
+
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no,
+ .index = -1};
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ (snapdata->depth_range[0] * local_scale), snapdata->mval,
+ ray_org_local, ray_normal_local);
+
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+
+ retval = true;
}
}
@@ -1717,11 +1614,9 @@ static bool snapEditMesh(
* \note Duplicate args here are documented at #snapObjectsRay
*/
static bool snapObject(
- SnapObjectContext *sctx,
+ SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit, const short snap_to, const float mval[2],
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
+ bool use_obedit,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1729,12 +1624,6 @@ static bool snapObject(
Object **r_ob, float r_obmat[4][4],
ListBase *r_hit_list)
{
- const enum eViewProj view_proj =
- ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE :
- (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO);
-
- const ARegion *ar = sctx->v3d_data.ar;
-
bool retval = false;
if (ob->type == OB_MESH) {
@@ -1743,9 +1632,7 @@ static bool snapObject(
if (use_obedit) {
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
- sctx, ob, em, obmat, ob_index,
- snap_to, mval, view_proj,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, ob, em, obmat, ob_index,
ray_depth, dist_px,
r_loc, r_no, r_index,
r_hit_list);
@@ -1762,9 +1649,8 @@ static bool snapObject(
dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(
- sctx, ob, dm, obmat, ob_index,
- snap_to, mval, view_proj, true,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, ob, dm, obmat, ob_index,
+ true,
ray_depth, dist_px,
r_loc, r_no,
r_index, r_hit_list);
@@ -1772,32 +1658,32 @@ static bool snapObject(
dm->release(dm);
}
}
- else if (snap_to != SCE_SNAP_MODE_FACE) {
+ else if (snapdata->snap_to != SCE_SNAP_MODE_FACE) {
if (ob->type == OB_ARMATURE) {
retval = snapArmature(
- ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal,
- mval, view_proj, depth_range, dist_px,
+ snapdata,
+ ob, ob->data, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
else if (ob->type == OB_CURVE) {
retval = snapCurve(
- ar, ob, ob->data, obmat, snap_to, mval, view_proj,
- depth_range,
- dist_px,
+ snapdata,
+ ob, ob->data, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
else if (ob->type == OB_EMPTY) {
retval = snapEmpty(
- ar, ob, obmat, snap_to, mval, view_proj,
- depth_range,
- dist_px,
+ snapdata,
+ ob, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
else if (ob->type == OB_CAMERA) {
retval = snapCamera(
- sctx, ob, obmat, snap_to, mval, view_proj,
- depth_range,
- dist_px,
+ sctx, snapdata, ob, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
}
@@ -1819,18 +1705,9 @@ static bool snapObject(
* Walks through all objects in the scene to find the closest snap element ray.
*
* \param sctx: Snap context to store data.
- * \param snap_to: Element to snap, Vertice, Edge or Face.
- * Currently only works one at a time, but can eventually operate as flag.
- *
+ * \param snapdata: struct generated in `get_snapdata`.
* \param snap_select: from enum SnapSelect.
- *
* \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
- * \param mval: Mouse coords.
- * When NULL, ray-casting is handled without any projection matrix correction.
- * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
- * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
- * \param ray_normal: Unit length direction of the ray.
- * \param depth_range: distances of clipe plane min and clip plane max;
*
* Read/Write Args
* ---------------
@@ -1851,11 +1728,9 @@ static bool snapObject(
*
*/
static bool snapObjectsRay(
- SnapObjectContext *sctx,
- const unsigned short snap_to, const SnapSelect snap_select,
- const bool use_object_edit_cage, const float mval[2],
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
+ SnapObjectContext *sctx, SnapData *snapdata,
+ const SnapSelect snap_select,
+ const bool use_object_edit_cage,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1873,14 +1748,12 @@ static bool snapObjectsRay(
*
* To solve that problem, we do it first as an exception.
* */
- Base *base_act = sctx->scene->basact;
+ BaseLegacy *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,
+ sctx, snapdata, ob, ob->obmat, ob_index++, false,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1896,11 +1769,11 @@ static bool snapObjectsRay(
ignore_object_active = true;
break;
}
- for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
+ for (BaseLegacy *base = sctx->scene->base.first; base != NULL; base = base->next) {
if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
- (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
+ (base->flag_legacy & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
- !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) ||
+ !((ignore_object_selected && (base->flag_legacy & (SELECT | BA_WAS_SEL))) ||
(ignore_object_active && base == base_act)))
{
Object *ob = base->object;
@@ -1914,9 +1787,8 @@ static bool snapObjectsRay(
Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
retval |= snapObject(
- sctx, dupli_snap, dupli_ob->mat, ob_index++,
- use_obedit_dupli, snap_to, mval,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, dupli_snap, dupli_ob->mat,
+ ob_index++, use_obedit_dupli,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1928,9 +1800,7 @@ static bool snapObjectsRay(
Object *ob_snap = use_obedit ? obedit : ob;
retval |= snapObject(
- sctx, ob_snap, ob->obmat, ob_index++,
- use_obedit, snap_to, mval,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1957,6 +1827,9 @@ SnapObjectContext *ED_transform_snap_object_context_create(
sctx->bmain = bmain;
sctx->scene = scene;
+ sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
+ sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
return sctx;
}
@@ -1971,11 +1844,6 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(
sctx->v3d_data.ar = ar;
sctx->v3d_data.v3d = v3d;
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
- sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- }
-
return sctx;
}
@@ -2007,10 +1875,8 @@ static void snap_object_data_free(void *sod_v)
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
{
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
- BLI_memarena_free(sctx->cache.mem_arena);
- }
+ BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
+ BLI_memarena_free(sctx->cache.mem_arena);
MEM_freeN(sctx);
}
@@ -2039,10 +1905,15 @@ bool ED_transform_snap_object_project_ray_ex(
Object **r_ob, float r_obmat[4][4])
{
const float depth_range[2] = {0.0f, FLT_MAX};
+
+ SnapData snapdata;
+ snap_data_set(
+ &snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE,
+ NULL, ray_start, ray_start, ray_normal, depth_range);
+
return snapObjectsRay(
- sctx,
- snap_to, params->snap_select, params->use_object_edit_cage, NULL,
- ray_start, ray_start, ray_normal, depth_range,
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
ray_depth, NULL,
r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
@@ -2071,10 +1942,13 @@ bool ED_transform_snap_object_project_ray_all(
float ray_depth_prev = ray_depth;
#endif
+ SnapData snapdata;
+ snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL,
+ ray_start, ray_start, ray_normal, depth_range);
+
bool retval = snapObjectsRay(
- sctx,
- snap_to, params->snap_select, params->use_object_edit_cage, NULL,
- ray_start, ray_start, ray_normal, depth_range,
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
&ray_depth, NULL,
NULL, NULL, NULL, NULL, NULL,
r_hit_list);
@@ -2153,19 +2027,40 @@ static bool transform_snap_context_project_view3d_mixed_impl(
BLI_assert(snap_to_flag != 0);
BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
- for (int i = 0; i < 3; i++) {
- if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
- if (use_depth == false) {
- ray_depth = BVH_RAYCAST_DIST_MAX;
+ if (use_depth) {
+ const float dist_px_orig = dist_px ? *dist_px : 0;
+ for (int i = 2; i >= 0; i--) {
+ if (snap_to_flag & (1 << i)) {
+ if (i == 0) {
+ BLI_assert(dist_px != NULL);
+ *dist_px = dist_px_orig;
+ }
+ if (ED_transform_snap_object_project_view3d(
+ sctx,
+ elem_type[i], params,
+ mval, dist_px, &ray_depth,
+ r_co, r_no))
+ {
+ /* 0.01 is a random but small value to prioritizing
+ * the first elements of the loop */
+ ray_depth += 0.01f;
+ is_hit = true;
+ }
}
-
- if (ED_transform_snap_object_project_view3d(
- sctx,
- elem_type[i], params,
- mval, dist_px, &ray_depth,
- r_co, r_no))
- {
- is_hit = true;
+ }
+ }
+ else {
+ for (int i = 0; i < 3; i++) {
+ if (snap_to_flag & (1 << i)) {
+ if (ED_transform_snap_object_project_view3d(
+ sctx,
+ elem_type[i], params,
+ mval, dist_px, &ray_depth,
+ r_co, r_no))
+ {
+ is_hit = true;
+ break;
+ }
}
}
}
@@ -2234,10 +2129,14 @@ bool ED_transform_snap_object_project_view3d_ex(
ray_depth = &ray_depth_fallback;
}
+ SnapData snapdata;
+ const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+ snap_data_set(&snapdata, ar, snap_to, view_proj, mval,
+ ray_origin, ray_start, ray_normal, depth_range);
+
return snapObjectsRay(
- sctx,
- snap_to, params->snap_select, params->use_object_edit_cage,
- mval, ray_origin, ray_start, ray_normal, depth_range,
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
ray_depth, dist_px,
r_loc, r_no, r_index, NULL, NULL, NULL);
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 5c5e84ee5f0..3510e1e7088 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -55,6 +55,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_uvedit.h"
@@ -70,7 +72,7 @@
/* use editmesh tessface */
#define USE_EDBM_LOOPTRIS
-static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset);
+static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, unsigned int pos);
void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
{
@@ -81,35 +83,67 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
mul_v2_fl(zoom, 256.0f * UI_DPI_FAC);
x_fac = zoom[0];
y_fac = zoom[1];
-
- cpack(0xFFFFFF);
+
glTranslate2fv(cursor);
- fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac);
- fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
- fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
- fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f);
- setlinestyle(4);
- cpack(0xFF);
- fdrawline(-0.05f * x_fac, 0.0f, 0.0f, 0.05f * y_fac);
- fdrawline(0.0f, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
- fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
- fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- setlinestyle(0.0f);
- cpack(0x0);
- fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f);
- fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f);
- fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
- fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
+ imm_cpack(0xFFFFFF);
+
+ immBegin(GL_LINE_LOOP, 4);
+ immVertex2f(pos, -0.05f * x_fac, 0.0f);
+ immVertex2f(pos, 0.0f, 0.05f * y_fac);
+ immVertex2f(pos, 0.05f * x_fac, 0.0f);
+ immVertex2f(pos, 0.0f, -0.05f * y_fac);
+ immEnd();
+
+ setlinestyle(4);
+ imm_cpack(0xFF);
+
+ /* drawing individual segments, because the stipple pattern
+ * gets messed up when drawing a continuous loop */
+ immBegin(GL_LINES, 8);
+ immVertex2f(pos, -0.05f * x_fac, 0.0f);
+ immVertex2f(pos, 0.0f, 0.05f * y_fac);
+ immVertex2f(pos, 0.0f, 0.05f * y_fac);
+ immVertex2f(pos, 0.05f * x_fac, 0.0f);
+ immVertex2f(pos, 0.05f * x_fac, 0.0f);
+ immVertex2f(pos, 0.0f, -0.05f * y_fac);
+ immVertex2f(pos, 0.0f, -0.05f * y_fac);
+ immVertex2f(pos, -0.05f * x_fac, 0.0f);
+ immEnd();
+
+ setlinestyle(0);
+ imm_cpack(0x0);
+
+ immBegin(GL_LINES, 8);
+ immVertex2f(pos, -0.020f * x_fac, 0.0f);
+ immVertex2f(pos, -0.1f * x_fac, 0.0f);
+ immVertex2f(pos, 0.1f * x_fac, 0.0f);
+ immVertex2f(pos, 0.020f * x_fac, 0.0f);
+ immVertex2f(pos, 0.0f, -0.020f * y_fac);
+ immVertex2f(pos, 0.0f, -0.1f * y_fac);
+ immVertex2f(pos, 0.0f, 0.1f * y_fac);
+ immVertex2f(pos, 0.0f, 0.020f * y_fac);
+ immEnd();
setlinestyle(1);
- cpack(0xFFFFFF);
- fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f);
- fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f);
- fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
- fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
+ imm_cpack(0xFFFFFF);
+
+ immBegin(GL_LINES, 8);
+ immVertex2f(pos, -0.020f * x_fac, 0.0f);
+ immVertex2f(pos, -0.1f * x_fac, 0.0f);
+ immVertex2f(pos, 0.1f * x_fac, 0.0f);
+ immVertex2f(pos, 0.020f * x_fac, 0.0f);
+ immVertex2f(pos, 0.0f, -0.020f * y_fac);
+ immVertex2f(pos, 0.0f, -0.1f * y_fac);
+ immVertex2f(pos, 0.0f, 0.1f * y_fac);
+ immVertex2f(pos, 0.0f, 0.020f * y_fac);
+ immEnd();
+
+ immUnbindProgram();
glTranslatef(-cursor[0], -cursor[1], 0.0);
setlinestyle(0);
@@ -141,12 +175,18 @@ static void draw_uvs_shadow(Object *obedit)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draws the mesh when painting */
- UI_ThemeColor(TH_UV_SHADOW);
+ immUniformThemeColor(TH_UV_SHADOW);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
}
+
+ immUnbindProgram();
}
static int draw_uvs_dm_shadow(DerivedMesh *dm)
@@ -212,19 +252,27 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) {
col[0] = 1.0;
col[1] = col[2] = 0.0;
- glColor3fv(col);
+
+ immUniformColor3fv(col);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- glBegin(GL_POLYGON);
+ immBegin(GL_TRIANGLE_FAN, efa->len);
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
- glEnd();
+
+ immEnd();
}
}
}
@@ -254,18 +302,23 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
areadiff = 1.0f - (area / uvarea);
weight_to_rgb(col, areadiff);
- glColor3fv(col);
+ immUniformColor3fv(col);
/* TODO: USE_EDBM_LOOPTRIS */
- glBegin(GL_POLYGON);
+ immBegin(GL_TRIANGLE_FAN, efa->len);
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
- glEnd();
+
+ immEnd();
}
}
}
+
+ immUnbindProgram();
+
break;
}
case SI_UVDT_STRETCH_ANGLE:
@@ -278,7 +331,13 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
BLI_buffer_declare_static(vec2f, auv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
col[3] = 0.5f; /* hard coded alpha, not that nice */
-
+
+ VertexFormat* format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
@@ -320,15 +379,15 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
}
/* TODO: USE_EDBM_LOOPTRIS */
- glBegin(GL_POLYGON);
+ immBegin(GL_TRIANGLE_FAN, efa->len);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
- glColor3fv(col);
- glVertex2fv(luv->uv);
+ immAttrib3fv(color, col);
+ immVertex2fv(pos, luv->uv);
}
- glEnd();
+ immEnd();
}
else {
if (tf == activetf)
@@ -337,6 +396,8 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
}
}
+ immUnbindProgram();
+
BLI_buffer_free(&uvang_buf);
BLI_buffer_free(&ang_buf);
BLI_buffer_free(&av_buf);
@@ -350,34 +411,38 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
BLI_buffer_free(&tf_uvorig_buf);
}
-static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset)
+static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, unsigned int pos)
{
BMIter liter;
BMLoop *l;
MLoopUV *luv;
- glBegin(GL_LINE_LOOP);
+ immBegin(GL_LINE_LOOP, efa->len);
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
- glEnd();
+
+ immEnd();
}
-static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly)
+static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly, unsigned int pos)
{
MLoopUV *mloopuv;
int i;
- glBegin(GL_LINE_LOOP);
+ immBegin(GL_LINE_LOOP, mpoly->totloop);
+
mloopuv = &me->mloopuv[mpoly->loopstart];
for (i = mpoly->totloop; i != 0; i--, mloopuv++) {
- glVertex2fv(mloopuv->uv);
+ immVertex2fv(pos, mloopuv->uv);
}
- glEnd();
+
+ immEnd();
}
-static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const int other_uv_filter)
+static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const int other_uv_filter, unsigned int pos)
{
Mesh *me = ob->data;
MPoly *mpoly = me->mpoly;
@@ -398,10 +463,10 @@ static void draw_uvs_other_mesh_texface(Object *ob, const Image *curimage, const
}
}
- draw_uvs_lineloop_mpoly(me, mpoly);
+ draw_uvs_lineloop_mpoly(me, mpoly, pos);
}
}
-static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, const int other_uv_filter)
+static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, const int other_uv_filter, unsigned int pos)
{
Mesh *me = ob->data;
MPoly *mpoly = me->mpoly;
@@ -453,38 +518,44 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage, c
}
}
- draw_uvs_lineloop_mpoly(me, mpoly);
+ draw_uvs_lineloop_mpoly(me, mpoly, pos);
}
}
static void draw_uvs_other_mesh(Object *ob, const Image *curimage, const bool new_shading_nodes,
- const int other_uv_filter)
+ const int other_uv_filter, unsigned int pos)
{
if (new_shading_nodes) {
- draw_uvs_other_mesh_new_shading(ob, curimage, other_uv_filter);
+ draw_uvs_other_mesh_new_shading(ob, curimage, other_uv_filter, pos);
}
else {
- draw_uvs_other_mesh_texface(ob, curimage, other_uv_filter);
+ draw_uvs_other_mesh_texface(ob, curimage, other_uv_filter, pos);
}
}
static void draw_uvs_other(Scene *scene, Object *obedit, const Image *curimage, const bool new_shading_nodes,
const int other_uv_filter)
{
- Base *base;
+ BaseLegacy *base;
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- UI_ThemeColor(TH_UV_OTHERS);
+ immUniformThemeColor(TH_UV_OTHERS);
for (base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
- if (!(base->flag & SELECT)) continue;
+ if (!(base->flag_legacy & SELECT)) continue;
if (!(base->lay & scene->lay)) continue;
if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
- draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter);
+ draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter, pos);
}
}
+
+ immUnbindProgram();
}
static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
@@ -498,8 +569,6 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
draw_uvs_other(scene, ob, curimage, new_shading_nodes, sima->other_uv_filter);
}
- UI_ThemeColor(TH_UV_SHADOW);
-
ma = give_current_material(ob, ob->actcol);
if (me->mtpoly) {
@@ -512,24 +581,34 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
mloopuv = me->mloopuv;
}
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_UV_SHADOW);
+
mloopuv_base = mloopuv;
for (a = me->totpoly; a > 0; a--, mpoly++) {
if ((scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE) && mpoly->mat_nr != ob->actcol - 1)
continue;
- glBegin(GL_LINE_LOOP);
+
+ immBegin(GL_LINE_LOOP, mpoly->totloop);
mloopuv = mloopuv_base + mpoly->loopstart;
for (b = 0; b < mpoly->totloop; b++, mloopuv++) {
- glVertex2fv(mloopuv->uv);
+ immVertex2fv(pos, mloopuv->uv);
}
- glEnd();
+
+ immEnd();
}
+
+ immUnbindProgram();
}
}
#ifdef USE_EDBM_LOOPTRIS
-static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset)
+static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset, unsigned int pos)
{
unsigned int i = *r_loop_index;
BMFace *f = em->looptris[i][0]->f;
@@ -537,7 +616,7 @@ static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const i
unsigned int j;
for (j = 0; j < 3; j++) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(em->looptris[i][j], cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
i++;
} while (i != em->tottri && (f == em->looptris[i][0]->f));
@@ -570,6 +649,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
+ unsigned int pos;
+
activetf = EDBM_mtexpoly_active_get(em, &efa_act, false, false); /* will be set to NULL if hidden */
#ifndef USE_EDBM_LOOPTRIS
activef = BM_mesh_active_face_get(bm, false, false);
@@ -622,7 +703,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
finaldm->release(finaldm);
}
}
-
+
/* 2. draw colored faces */
if (sima->flag & SI_DRAW_STRETCH) {
@@ -638,6 +719,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
#ifdef USE_EDBM_LOOPTRIS
{
unsigned int i;
+
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
for (i = 0; i < em->tottri; i++) {
efa = em->looptris[i][0]->f;
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
@@ -647,26 +733,22 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if (tf == activetf) {
/* only once */
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
- UI_ThemeColor4(TH_EDITMESH_ACTIVE);
+ immUniformThemeColor(TH_EDITMESH_ACTIVE);
}
else {
- glColor4ubv((GLubyte *)(is_select ? col2 : col1));
+ immUniformColor4ubv(is_select ? col2 : col1);
}
- glBegin(GL_TRIANGLES);
- draw_uvs_looptri(em, &i, cd_loop_uv_offset);
- glEnd();
-
- if (tf == activetf) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
+ immBegin(GL_TRIANGLES, (em->looptris[i][0]->f->len - 2) * 3);
+ draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
+ immEnd();
}
else {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
+
+ immUnbindProgram();
}
#else
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
@@ -751,104 +833,152 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
switch (sima->dt_uv) {
case SI_UVDT_DASH:
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (tf) {
- cpack(0x111111);
+ imm_cpack(0x111111);
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
setlinestyle(2);
- cpack(0x909090);
+ imm_cpack(0x909090);
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
setlinestyle(0);
}
}
+
+ immUnbindProgram();
+
break;
case SI_UVDT_BLACK: /* black/white */
- case SI_UVDT_WHITE:
- if (sima->dt_uv == SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f);
- else glColor3f(0.0f, 0.0f, 0.0f);
+ case SI_UVDT_WHITE:
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ if (sima->dt_uv == SI_UVDT_WHITE) {
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ }
+ else {
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ }
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
}
+
+ immUnbindProgram();
+
break;
case SI_UVDT_OUTLINE:
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glLineWidth(3);
- cpack(0x0);
-
+ imm_cpack(0x0);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
}
-
+
+ immUnbindProgram();
+
glLineWidth(1);
UI_GetThemeColor4ubv(TH_WIRE_EDIT, col2);
- glColor4ubv((unsigned char *)col2);
if (me->drawflag & ME_DRAWEDGES) {
- int sel, lastsel = -1;
+ int sel;
UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1);
+ VertexFormat* format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
if (interpedges) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- glBegin(GL_LINE_LOOP);
+ immBegin(GL_LINE_LOOP, efa->len);
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
- glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
+ immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
- glEnd();
+
+ immEnd();
}
+
+ immUnbindProgram();
}
else {
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ int lastsel = -1;
+
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- glBegin(GL_LINES);
+ immBegin(GL_LINES, efa->len * 2);
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
sel = uvedit_edge_select_test(scene, l, cd_loop_uv_offset);
if (sel != lastsel) {
- glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
+ immAttrib4ubv(color, sel ? (GLubyte *)col1 : (GLubyte *)col2);
lastsel = sel;
}
+
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
- glEnd();
+
+ immEnd();
}
+
+ immUnbindProgram();
}
}
else {
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(col2);
+
/* no nice edges */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
}
+
+ immUnbindProgram();
}
-
+
break;
}
@@ -861,50 +991,80 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if (drawfaces) {
float cent[2];
-
+ bool col_set = false;
+
+ VertexFormat* format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
glPointSize(pointsize);
- glBegin(GL_POINTS);
+ immBeginAtMost(GL_POINTS, bm->totface);
/* unselected faces */
- UI_ThemeColor(TH_WIRE);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
+ /* Only set color for the first face */
+ if (!col_set) {
+ UI_GetThemeColor3ubv(TH_WIRE, col1);
+ immAttrib3ubv(color, col1);
+
+ col_set = true;
+ }
+
uv_poly_center(efa, cent, cd_loop_uv_offset);
- glVertex2fv(cent);
+ immVertex2fv(pos, cent);
}
}
+ col_set = false;
+
/* selected faces */
- UI_ThemeColor(TH_FACE_DOT);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
+ /* Only set color for the first face */
+ if (!col_set) {
+ UI_GetThemeColor3ubv(TH_FACE_DOT, col1);
+ immAttrib3ubv(color, col1);
+
+ col_set = true;
+ }
+
uv_poly_center(efa, cent, cd_loop_uv_offset);
- glVertex2fv(cent);
+ immVertex2fv(pos, cent);
}
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* 6. draw uv vertices */
if (drawfaces != 2) { /* 2 means Mesh Face Mode */
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* unselected uvs */
- UI_ThemeColor(TH_VERTEX);
+ immUniformThemeColor(TH_VERTEX);
pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
glPointSize(pointsize);
-
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GL_POINTS, bm->totloop);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
@@ -912,17 +1072,19 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
}
- glEnd();
+
+ immEnd();
/* pinned uvs */
/* give odd pointsizes odd pin pointsizes */
glPointSize(pointsize * 2 + (((int)pointsize % 2) ? (-1) : 0));
- cpack(0xFF);
+ imm_cpack(0xFF);
- glBegin(GL_POINTS);
+ immBeginAtMost(GL_POINTS, bm->totloop);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
@@ -931,16 +1093,18 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_PINNED)
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
}
- glEnd();
+
+ immEnd();
/* selected uvs */
- UI_ThemeColor(TH_VERTEX_SELECT);
+ immUniformThemeColor(TH_VERTEX_SELECT);
glPointSize(pointsize);
- glBegin(GL_POINTS);
+ immBeginAtMost(GL_POINTS, bm->totloop);
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
@@ -949,10 +1113,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
- glVertex2fv(luv->uv);
+ immVertex2fv(pos, luv->uv);
}
}
- glEnd();
+
+ immEnd();
+
+ immUnbindProgram();
}
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index f63cf771120..0e03ab84a47 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -127,7 +127,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
BKE_scene_set_background(freestyle_bmain, freestyle_scene);
// Camera
- Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL);
+ Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, (SceneLayer *)freestyle_scene->render_layers.first, OB_CAMERA, NULL);
DAG_relations_tag_update(freestyle_bmain);
Camera *camera = (Camera *)object_camera->data;
@@ -166,7 +166,7 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
// compositor has finished.
// release objects and data blocks
- for (Base *b = (Base *)freestyle_scene->base.first; b; b = b->next) {
+ for (BaseLegacy *b = (BaseLegacy *)freestyle_scene->base.first; b; b = b->next) {
Object *ob = b->object;
void *data = ob->data;
char *name = ob->id.name;
@@ -674,7 +674,7 @@ int BlenderStrokeRenderer::get_stroke_count() const
void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
{
#if 0
- Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH);
+ Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, (SceneLayer *)freestyle_scene->render_layers.first, OB_MESH);
DAG_relations_tag_update(freestyle_bmain);
#else
Object *object_mesh = NewMesh();
@@ -922,7 +922,7 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
Object *BlenderStrokeRenderer::NewMesh() const
{
Object *ob;
- Base *base;
+ BaseLegacy *base;
char name[MAX_ID_NAME];
unsigned int mesh_id = get_stroke_mesh_id();
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 76b76bb636a..7573985baa8 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../draw
../editors/include
@@ -64,6 +65,7 @@ set(SRC
intern/gpu_select.c
intern/gpu_shader.c
intern/gpu_texture.c
+ intern/gpu_uniformbuffer.c
intern/gpu_viewport.c
gawain/attrib_binding.c
@@ -122,6 +124,7 @@ set(SRC
GPU_select.h
GPU_shader.h
GPU_texture.h
+ GPU_uniformbuffer.h
GPU_viewport.h
intern/gpu_codegen.h
@@ -130,6 +133,8 @@ set(SRC
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_checker_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC)
@@ -148,8 +153,16 @@ 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_3D_passthrough_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.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)
@@ -175,6 +188,8 @@ data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.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_keyframe_diamond_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fire_frag.glsl SRC)
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index bc3017e2784..066bc9eeba7 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -35,3 +35,9 @@
/* Extend Batch_set_program to use Blender’s library of built-in shader programs. */
void Batch_set_builtin_program(Batch*, GPUBuiltinShader);
+
+/* Replacement for gluSphere */
+Batch *Batch_get_sphere(int lod);
+
+void gpu_batch_init(void);
+void gpu_batch_exit(void);
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 31ad8243c4b..ff00a83d00b 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -53,6 +53,8 @@ int GPU_max_textures(void);
float GPU_max_texture_anisotropy(void);
int GPU_max_color_texture_samples(void);
int GPU_max_cube_map_size(void);
+int GPU_max_ubo_binds(void);
+int GPU_max_ubo_size(void);
int GPU_color_depth(void);
void GPU_get_dfdy_factors(float fac[2]);
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 989b874fd38..9611a6f0577 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -52,6 +52,7 @@ void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
GPUFrameBuffer *GPU_framebuffer_create(void);
bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
+void GPU_framebuffer_bind(GPUFrameBuffer *fb);
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
index 4390b62379e..43a03f8e4b6 100644
--- a/source/blender/gpu/GPU_matrix.h
+++ b/source/blender/gpu/GPU_matrix.h
@@ -133,6 +133,9 @@ const float *gpuGetNormalMatrixInverse(float m[3][3]);
#if SUPPORT_LEGACY_MATRIX
/* copy top matrix from each legacy stack into new fresh stack */
void gpuMatrixBegin3D_legacy(void);
+
+/* call after using glScale, glTranslate, etc. between draw calls */
+void gpuMatrixUpdate_legacy(void);
#endif
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index e528089850c..fcf070890ea 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -38,6 +38,7 @@ extern "C" {
typedef struct GPUShader GPUShader;
struct GPUTexture;
+struct GPUUniformBuffer;
/* GPU Shader
* - only for fragment shaders now
@@ -69,14 +70,17 @@ void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
void GPU_shader_unbind(void);
+int GPU_shader_get_program(GPUShader *shader);
void *GPU_shader_get_interface(GPUShader *shader);
void GPU_shader_set_interface(GPUShader *shader, void *interface);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
+int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
int arraysize, const float *value);
void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
int arraysize, const int *value);
+void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
@@ -97,13 +101,17 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_EDGES_FRONT_BACK_ORTHO,
GPU_SHADER_EDGES_OVERLAY_SIMPLE,
GPU_SHADER_EDGES_OVERLAY,
+ GPU_SHADER_KEYFRAME_DIAMOND,
+ GPU_SHADER_SIMPLE_LIGHTING,
/* for simple 2D drawing */
GPU_SHADER_2D_UNIFORM_COLOR,
GPU_SHADER_2D_FLAT_COLOR,
GPU_SHADER_2D_SMOOTH_COLOR,
GPU_SHADER_2D_IMAGE_COLOR,
+ GPU_SHADER_2D_CHECKER,
/* for simple 3D drawing */
GPU_SHADER_3D_UNIFORM_COLOR,
+ GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE,
GPU_SHADER_3D_FLAT_COLOR,
GPU_SHADER_3D_SMOOTH_COLOR,
GPU_SHADER_3D_DEPTH_ONLY,
@@ -127,6 +135,13 @@ typedef enum GPUBuiltinShader {
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,
+ /* lamp drawing */
+ GPU_SHADER_3D_GROUNDPOINT,
+ GPU_SHADER_3D_GROUNDLINE,
+ GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR,
+ /* instance */
+ GPU_SHADER_INSTANCE_UNIFORM_COLOR,
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE,
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 756fe79151b..a8df80cd626 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -55,25 +55,112 @@ typedef struct GPUTexture GPUTexture;
* - if created with from_blender, will not free the texture
*/
-typedef enum GPUHDRType {
- GPU_HDR_NONE = 0,
- GPU_HDR_HALF_FLOAT = 1,
- GPU_HDR_FULL_FLOAT = (1 << 1),
-} GPUHDRType;
+/* Wrapper to supported OpenGL/Vulkan texture internal storage
+ * If you need a type just uncomment it. Be aware that some formats
+ * are not supported by renderbuffers. All of the following formats
+ * are part of the OpenGL 3.3 core
+ * specification. */
+typedef enum GPUTextureFormat {
+ /* Formats texture & renderbuffer */
+ GPU_RGBA16F,
+ GPU_RGBA8,
+ GPU_RG32F,
+ GPU_RG16F,
+ GPU_R8,
+#if 0
+ GPU_RGBA32F,
+ GPU_RGBA32I,
+ GPU_RGBA32UI,
+ GPU_RGBA16,
+ GPU_RGBA16I,
+ GPU_RGBA16UI,
+ GPU_RGBA8I,
+ GPU_RGBA8UI,
+ GPU_RG32I,
+ GPU_RG32UI,
+ GPU_RG16,
+ GPU_RG16I,
+ GPU_RG16UI,
+ GPU_RG8,
+ GPU_RG8I,
+ GPU_RG8UI,
+ GPU_R32F,
+ GPU_R32I,
+ GPU_R32UI,
+ GPU_R16F,
+ GPU_R16I,
+ GPU_R16UI,
+ GPU_R16,
+ GPU_R8I,
+ GPU_R8UI,
+#endif
+
+ /* Special formats texture & renderbuffer */
+#if 0
+ GPU_R11F_G11F_B10F,
+ GPU_RGB10_A2,
+ GPU_RGB10_A2UI,
+ GPU_DEPTH32F_STENCIL8,
+ GPU_DEPTH24_STENCIL8,
+#endif
+
+ /* Texture only format */
+#if 0
+ GPU_RGBA16_SNORM,
+ GPU_RGBA8_SNORM,
+ GPU_RGB32F,
+ GPU_RGB32I,
+ GPU_RGB32UI,
+ GPU_RGB16_SNORM,
+ GPU_RGB16F,
+ GPU_RGB16I,
+ GPU_RGB16UI,
+ GPU_RGB16,
+ GPU_RGB8_SNORM,
+ GPU_RGB8,
+ GPU_RGB8I,
+ GPU_RGB8UI,
+ GPU_RG16_SNORM,
+ GPU_RG8_SNORM,
+ GPU_R16_SNORM,
+ GPU_R8_SNORM,
+#endif
+
+ /* Special formats texture only */
+#if 0
+ GPU_SRGB8_A8,
+ GPU_SRGB8,
+ GPU_RGB9_E5,
+ GPU_COMPRESSED_RG_RGTC2,
+ GPU_COMPRESSED_SIGNED_RG_RGTC2,
+ GPU_COMPRESSED_RED_RGTC1,
+ GPU_COMPRESSED_SIGNED_RED_RGTC1,
+#endif
+
+ /* Depth Formats */
+ GPU_DEPTH_COMPONENT32F,
+ GPU_DEPTH_COMPONENT24,
+ GPU_DEPTH_COMPONENT16,
+} GPUTextureFormat;
GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
+GPUTexture *GPU_texture_create_1D_custom(
+ int w, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_custom(
+ int w, int h, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_array(int w, int h, int d, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_3D_custom(
+ int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_multisample(
- int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
+
GPUTexture *GPU_texture_from_blender(
struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
+
void GPU_invalid_tex_init(void);
void GPU_invalid_tex_bind(int mode);
void GPU_invalid_tex_free(void);
@@ -81,12 +168,13 @@ void GPU_invalid_tex_free(void);
void GPU_texture_free(GPUTexture *tex);
void GPU_texture_ref(GPUTexture *tex);
-
void GPU_texture_bind(GPUTexture *tex, int number);
void GPU_texture_unbind(GPUTexture *tex);
int GPU_texture_bound_number(GPUTexture *tex);
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare);
+void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat);
struct GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
int GPU_texture_framebuffer_attachment(GPUTexture *tex);
diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h
new file mode 100644
index 00000000000..bcb6e1077b7
--- /dev/null
+++ b/source/blender/gpu/GPU_uniformbuffer.h
@@ -0,0 +1,44 @@
+/*
+ * ***** 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): Clement Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_uniformbuffer.h
+ * \ingroup gpu
+ */
+
+typedef struct GPUUniformBuffer GPUUniformBuffer;
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]);
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo);
+
+void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data);
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number);
+#if 0
+void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo);
+#endif
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo);
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index fce509377ab..9de16f64ca1 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -34,12 +34,57 @@
#include <stdbool.h>
+#include "DNA_vec_types.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_texture.h"
+
typedef struct GPUViewport GPUViewport;
-GPUViewport *GPU_viewport_create(void);
+#define MAX_BUFFERS 8
+#define MAX_TEXTURES 16
+#define MAX_PASSES 16
+#define MAX_STORAGE 2 /* extend if needed */
+
+/* All FramebufferLists are just the same pointers with different names */
+typedef struct FramebufferList {
+ struct GPUFrameBuffer *framebuffers[MAX_BUFFERS];
+} FramebufferList;
+
+typedef struct TextureList {
+ struct GPUTexture *textures[MAX_TEXTURES];
+} TextureList;
+
+typedef struct PassList {
+ struct DRWPass *passes[MAX_TEXTURES];
+} PassList;
+typedef struct StorageList {
+ void *storage[MAX_STORAGE]; /* custom structs from the engine */
+} StorageList;
+
+/* Buffer and textures used by the viewport by default */
+typedef struct DefaultFramebufferList {
+ struct GPUFrameBuffer *default_fb;
+} DefaultFramebufferList;
+
+typedef struct DefaultTextureList {
+ struct GPUTexture *color;
+ struct GPUTexture *depth;
+} DefaultTextureList;
+
+typedef struct DefaultPassList {
+ struct DRWPass *non_meshes_pass;
+ struct DRWPass *ob_center_pass;
+} DefaultPassList;
+
+GPUViewport *GPU_viewport_create(void);
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine);
+void GPU_viewport_unbind(GPUViewport *viewport);
void GPU_viewport_free(GPUViewport *viewport);
+void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str);
+
/* debug */
bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]);
void GPU_viewport_debug_depth_free(GPUViewport *viewport);
diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c
index a60865d41d2..55ccd94a555 100644
--- a/source/blender/gpu/gawain/batch.c
+++ b/source/blender/gpu/gawain/batch.c
@@ -19,20 +19,25 @@ extern bool gpuMatricesDirty(void); // how best to use this here?
Batch* Batch_create(PrimitiveType prim_type, VertexBuffer* verts, ElementList* elem)
{
+ Batch* batch = calloc(1, sizeof(Batch));
+
+ Batch_init(batch, prim_type, verts, elem);
+
+ return batch;
+ }
+
+void Batch_init(Batch* batch, PrimitiveType prim_type, VertexBuffer* verts, ElementList* elem)
+ {
#if TRUST_NO_ONE
assert(verts != NULL);
assert(prim_type == PRIM_POINTS || prim_type == PRIM_LINES || prim_type == PRIM_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_discard(Batch* batch)
@@ -247,3 +252,89 @@ void Batch_draw(Batch* batch)
Batch_done_using_program(batch);
glBindVertexArray(0);
}
+
+
+
+// clement : temp stuff
+void Batch_draw_stupid(Batch* batch)
+{
+ if (batch->vao_id)
+ glBindVertexArray(batch->vao_id);
+ else
+ Batch_prime(batch);
+
+ if (batch->program_dirty)
+ Batch_update_program_bindings(batch);
+
+ // Batch_use_program(batch);
+
+ //gpuBindMatrices(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);
+
+ // Batch_done_using_program(batch);
+ glBindVertexArray(0);
+}
+
+// clement : temp stuff
+void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count,
+ int attrib_nbr, int attrib_stride, int attrib_size[16], int attrib_loc[16])
+{
+ if (batch->vao_id)
+ glBindVertexArray(batch->vao_id);
+ else
+ Batch_prime(batch);
+
+ if (batch->program_dirty)
+ Batch_update_program_bindings(batch);
+
+ glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
+ int ptr_ofs = 0;
+ for (int i = 0; i < attrib_nbr; ++i) {
+ int size = attrib_size[i];
+ int loc = attrib_loc[i];
+ int atr_ofs = 0;
+
+ while (size > 0) {
+ glEnableVertexAttribArray(loc + atr_ofs);
+ glVertexAttribPointer(loc + atr_ofs, (size > 4) ? 4 : size, GL_FLOAT, GL_FALSE,
+ sizeof(float) * attrib_stride, (GLvoid*)(sizeof(float) * ptr_ofs));
+ glVertexAttribDivisor(loc + atr_ofs, 1);
+ atr_ofs++;
+ ptr_ofs += (size > 4) ? 4 : size;
+ size -= 4;
+ }
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ // Batch_use_program(batch);
+
+ //gpuBindMatrices(batch->program);
+
+ if (batch->elem)
+ {
+ const ElementList* el = batch->elem;
+
+ glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count);
+ }
+ else
+ glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count);
+
+ // Batch_done_using_program(batch);
+ glBindVertexArray(0);
+}
+
diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h
index 932ee182703..660ed9eb762 100644
--- a/source/blender/gpu/gawain/batch.h
+++ b/source/blender/gpu/gawain/batch.h
@@ -38,6 +38,7 @@ typedef struct Batch{
} Batch;
Batch* Batch_create(PrimitiveType, VertexBuffer*, ElementList*);
+void Batch_init(Batch*, PrimitiveType, VertexBuffer*, ElementList*);
void Batch_discard(Batch*); // verts & elem are not discarded
void Batch_discard_all(Batch*); // including verts & elem
@@ -59,6 +60,12 @@ void Batch_Uniform4fv(Batch*, const char* name, const float data[4]);
void Batch_draw(Batch*);
+// clement : temp stuff
+void Batch_draw_stupid(Batch*);
+void Batch_draw_stupid_instanced(Batch*, unsigned int instance_vbo, int instance_count,
+ int attrib_nbr, int attrib_stride, int attrib_loc[16], int attrib_size[16]);
+
+
diff --git a/source/blender/gpu/gawain/buffer_id.cpp b/source/blender/gpu/gawain/buffer_id.cpp
index a7b8d7a394a..450656c4ebf 100644
--- a/source/blender/gpu/gawain/buffer_id.cpp
+++ b/source/blender/gpu/gawain/buffer_id.cpp
@@ -53,7 +53,7 @@ GLuint buffer_id_alloc()
}
orphan_mutex.unlock();
- GLuint new_buffer_id;
+ GLuint new_buffer_id = 0;
glGenBuffers(1, &new_buffer_id);
return new_buffer_id;
}
@@ -80,8 +80,6 @@ GLuint vao_id_alloc()
assert(thread_is_main());
#endif
- GLuint new_vao_id;
-
// delete orphaned IDs
orphan_mutex.lock();
if (!orphaned_vao_ids.empty())
@@ -95,6 +93,7 @@ GLuint vao_id_alloc()
}
orphan_mutex.unlock();
+ GLuint new_vao_id = 0;
glGenVertexArrays(1, &new_vao_id);
return new_vao_id;
}
diff --git a/source/blender/gpu/gawain/immediate.c b/source/blender/gpu/gawain/immediate.c
index 3806b0f304a..b7aad530620 100644
--- a/source/blender/gpu/gawain/immediate.c
+++ b/source/blender/gpu/gawain/immediate.c
@@ -54,7 +54,7 @@ typedef struct {
static PER_THREAD bool initialized = false;
static PER_THREAD Immediate imm;
-void immInit()
+void immInit(void)
{
#if TRUST_NO_ONE
assert(!initialized);
@@ -80,7 +80,7 @@ void immInit()
immActivate();
}
-void immActivate()
+void immActivate(void)
{
#if TRUST_NO_ONE
assert(initialized);
@@ -91,7 +91,7 @@ void immActivate()
imm.vao_id = vao_id_alloc();
}
-void immDeactivate()
+void immDeactivate(void)
{
#if TRUST_NO_ONE
assert(initialized);
@@ -104,14 +104,14 @@ void immDeactivate()
imm.prev_enabled_attrib_bits = 0;
}
-void immDestroy()
+void immDestroy(void)
{
immDeactivate();
buffer_id_free(imm.vbo_id);
initialized = false;
}
-VertexFormat* immVertexFormat()
+VertexFormat* immVertexFormat(void)
{
VertexFormat_clear(&imm.vertex_format);
return &imm.vertex_format;
@@ -134,7 +134,7 @@ void immBindProgram(GLuint program)
gpuBindMatrices(program);
}
-void immUnbindProgram()
+void immUnbindProgram(void)
{
#if TRUST_NO_ONE
assert(imm.bound_program != 0);
@@ -339,7 +339,7 @@ static void immDrawSetup(void)
gpuBindMatrices(imm.bound_program);
}
-void immEnd()
+void immEnd(void)
{
#if TRUST_NO_ONE
assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair
@@ -727,6 +727,50 @@ void immUniform1f(const char* name, float x)
glUniform1f(loc, x);
}
+void immUniform2f(const char* name, float x, float y)
+{
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform2f(loc, x, y);
+}
+
+void immUniform2fv(const char* name, const float data[2])
+{
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform2fv(loc, 1, data);
+}
+
+void immUniform3f(const char* name, float x, float y, float z)
+ {
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform3f(loc, x, y, z);
+ }
+
+void immUniform3fv(const char* name, const float data[3])
+ {
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform3fv(loc, 1, data);
+ }
+
void immUniform4f(const char* name, float x, float y, float z, float w)
{
int loc = glGetUniformLocation(imm.bound_program, name);
diff --git a/source/blender/gpu/gawain/immediate.h b/source/blender/gpu/gawain/immediate.h
index 23d7413aaf8..53f9e6c46e1 100644
--- a/source/blender/gpu/gawain/immediate.h
+++ b/source/blender/gpu/gawain/immediate.h
@@ -79,6 +79,10 @@ 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 immUniform2f(const char* name, float x, float y);
+void immUniform2fv(const char* name, const float data[2]);
+void immUniform3f(const char* name, float x, float y, float z);
+void immUniform3fv(const char* name, const float data[3]);
void immUniform4f(const char* name, float x, float y, float z, float w);
void immUniform4fv(const char* name, const float data[4]);
void immUniformMat4(const char* name, const float data[4][4]);
diff --git a/source/blender/gpu/gawain/vertex_buffer.c b/source/blender/gpu/gawain/vertex_buffer.c
index 5f2da60067d..827703403e3 100644
--- a/source/blender/gpu/gawain/vertex_buffer.c
+++ b/source/blender/gpu/gawain/vertex_buffer.c
@@ -16,7 +16,7 @@
#define KEEP_SINGLE_COPY 1
-VertexBuffer* VertexBuffer_create()
+VertexBuffer* VertexBuffer_create(void)
{
VertexBuffer* verts = malloc(sizeof(VertexBuffer));
VertexBuffer_init(verts);
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 23f9f68f1aa..716c5e55b3c 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -25,6 +25,9 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
#include "GPU_batch.h"
#include "gpu_shader_private.h"
@@ -33,3 +36,87 @@ 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);
}
+
+static Batch *sphere_high = NULL;
+static Batch *sphere_med = NULL;
+static Batch *sphere_low = NULL;
+
+static VertexBuffer *vbo;
+static VertexFormat format = {0};
+static unsigned int pos_id, nor_id;
+static unsigned int vert;
+
+static void batch_sphere_lat_lon_vert(float lat, float lon)
+{
+ float pos[3];
+ pos[0] = sinf(lat) * cosf(lon);
+ pos[1] = cosf(lat);
+ pos[2] = sinf(lat) * sinf(lon);
+
+ setAttrib(vbo, nor_id, vert, pos);
+ setAttrib(vbo, pos_id, vert++, pos);
+}
+
+/* Replacement for gluSphere */
+static Batch *batch_sphere(int lat_res, int lon_res)
+{
+ const float lon_inc = 2 * M_PI / lon_res;
+ const float lat_inc = M_PI / lat_res;
+ float lon, lat;
+
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, (lat_res-1) * lon_res * 6);
+ vert = 0;
+
+ lon = 0.0f;
+ for(int i = 0; i < lon_res; i++, lon += lon_inc) {
+ lat = 0.0f;
+ for(int j = 0; j < lat_res; j++, lat += lat_inc) {
+ if (j != lat_res - 1) { /* Pole */
+ batch_sphere_lat_lon_vert(lat, lon);
+ batch_sphere_lat_lon_vert(lat+lat_inc, lon);
+ batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc);
+ }
+
+ if (j != 0) { /* Pole */
+ batch_sphere_lat_lon_vert(lat, lon);
+ batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc);
+ batch_sphere_lat_lon_vert(lat, lon+lon_inc);
+ }
+ }
+ }
+
+ return Batch_create(GL_TRIANGLES, vbo, NULL);
+}
+
+Batch *Batch_get_sphere(int lod)
+{
+ BLI_assert(lod >= 0 && lod <= 2);
+
+ if (lod == 0)
+ return sphere_low;
+ else if (lod == 1)
+ return sphere_med;
+ else
+ return sphere_high;
+}
+
+void gpu_batch_init(void)
+{
+ /* Hard coded resolution */
+ sphere_low = batch_sphere(8, 8);
+ sphere_med = batch_sphere(16, 10);
+ sphere_high = batch_sphere(32, 24);
+}
+
+void gpu_batch_exit(void)
+{
+ Batch_discard_all(sphere_low);
+ Batch_discard_all(sphere_med);
+ Batch_discard_all(sphere_high);
+}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 211394e7932..4223ec54f74 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -1192,7 +1192,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
#if 0
input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
#endif
- input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
+ input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
input->textarget = GL_TEXTURE_2D;
MEM_freeN(link->ptr1);
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 13596f2a0de..528bdefc209 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -225,7 +225,13 @@ static GPUTexture * create_concentric_sample_texture(int side)
}
}
- tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
+ tex = GPU_texture_create_1D_custom(side * side, 2, GPU_RG16F, (float *)texels, NULL);
+
+ /* Set parameters */
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, false);
+ GPU_texture_unbind(tex);
+
MEM_freeN(texels);
return tex;
}
@@ -247,7 +253,13 @@ static GPUTexture *create_spiral_sample_texture(int numsaples)
texels[i][1] = r * sinf(phi);
}
- tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL);
+ tex = GPU_texture_create_1D_custom(numsaples, 2, GPU_RG16F, (float *)texels, NULL);
+
+ /* Set parameters */
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, false);
+ GPU_texture_unbind(tex);
+
MEM_freeN(texels);
return tex;
}
@@ -358,6 +370,7 @@ void GPU_fx_compositor_destroy(GPUFX *fx)
static GPUTexture * create_jitter_texture(void)
{
+ GPUTexture *tex;
float jitter[64 * 64][2];
int i;
@@ -367,7 +380,15 @@ static GPUTexture * create_jitter_texture(void)
normalize_v2(jitter[i]);
}
- return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL);
+ tex = GPU_texture_create_2D_custom(64, 64, 2, GPU_RG16F, &jitter[0][0], NULL);
+
+ /* Set parameters */
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, false);
+ GPU_texture_wrap_mode(tex, true);
+ GPU_texture_unbind(tex);
+
+ return tex;
}
@@ -433,7 +454,7 @@ bool GPU_fx_compositor_initialize_passes(
if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
cleanup_fx_gl_data(fx, false);
- if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, err_out))) {
printf(".256%s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
@@ -485,38 +506,42 @@ bool GPU_fx_compositor_initialize_passes(
{
if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
- if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out)))
+
+ if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_custom(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RG16F, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
+ GPU_texture_bind(fx->dof_nearfar_coc, 0);
+ GPU_texture_filter_mode(fx->dof_nearfar_coc, false);
+ GPU_texture_wrap_mode(fx->dof_nearfar_coc, false);
+ GPU_texture_unbind(fx->dof_nearfar_coc);
-
- if (!(fx->dof_near_blur = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ if (!(fx->dof_near_blur = GPU_texture_create_2D_custom(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RGBA16F, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
- if (!(fx->dof_far_blur = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ if (!(fx->dof_far_blur = GPU_texture_create_2D_custom(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RGBA16F, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
@@ -531,21 +556,21 @@ bool GPU_fx_compositor_initialize_passes(
if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
@@ -564,7 +589,7 @@ bool GPU_fx_compositor_initialize_passes(
/* we need to pass data between shader stages, allocate an extra color buffer */
if (num_passes > 1) {
if (!fx->color_buffer_sec) {
- if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, err_out))) {
printf(".256%s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
@@ -692,14 +717,16 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
GPU_shader_bind(depth_resolve_shader);
GPU_texture_bind(fx->depth_buffer_xray, 0);
- GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer_xray, false);
+ GPU_texture_filter_mode(fx->depth_buffer_xray, true);
GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray);
/* draw */
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
- GPU_texture_filter_mode(fx->depth_buffer_xray, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer_xray, true);
+ GPU_texture_filter_mode(fx->depth_buffer_xray, false);
GPU_texture_unbind(fx->depth_buffer_xray);
GPU_shader_unbind();
@@ -814,7 +841,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(ssao_shader, interface->color_uniform, src);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(ssao_shader, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(fx->jitter_buffer, numslots++);
@@ -830,7 +858,8 @@ bool GPU_fx_do_composite_pass(
/* disable bindings */
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_texture_unbind(fx->jitter_buffer);
GPU_texture_unbind(fx->ssao_spiral_samples_tex);
@@ -906,12 +935,13 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(src, numslots++);
/* disable filtering for the texture so custom downsample can do the right thing */
- GPU_texture_filter_mode(src, false, false);
+ GPU_texture_filter_mode(src, false);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src);
/* target is the downsampled coc buffer */
@@ -925,9 +955,10 @@ bool GPU_fx_do_composite_pass(
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
- GPU_texture_filter_mode(src, false, true);
+ GPU_texture_filter_mode(src, true);
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
@@ -958,7 +989,7 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far);
- GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_far, false);
/* target is the downsampled coc buffer */
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0);
@@ -978,7 +1009,7 @@ bool GPU_fx_do_composite_pass(
GPU_framebuffer_texture_detach(fx->dof_far_blur);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
- GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_near, false);
selection[0] = 1.0f;
selection[1] = 0.0f;
@@ -1018,14 +1049,15 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_near_blur, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->near_uniform, fx->dof_near_blur);
- GPU_texture_filter_mode(fx->dof_near_blur, false, true);
+ GPU_texture_filter_mode(fx->dof_near_blur, true);
GPU_texture_bind(fx->dof_far_blur, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->far_uniform, fx->dof_far_blur);
- GPU_texture_filter_mode(fx->dof_far_blur, false, true);
+ GPU_texture_filter_mode(fx->dof_far_blur, true);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_shader_uniform_texture(dof_shader_pass3, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(src, numslots++);
@@ -1040,7 +1072,7 @@ bool GPU_fx_do_composite_pass(
GPU_texture_unbind(fx->dof_near_blur);
GPU_texture_unbind(fx->dof_far_blur);
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
GPU_texture_unbind(fx->depth_buffer);
/* may not be attached, in that case this just returns */
@@ -1100,7 +1132,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass1, interface->color_uniform, src);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
/* target is the downsampled coc buffer */
@@ -1111,7 +1144,8 @@ bool GPU_fx_do_composite_pass(
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
@@ -1137,7 +1171,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_vector(dof_shader_pass2, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(dof_shader_pass2, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
@@ -1165,7 +1200,8 @@ bool GPU_fx_do_composite_pass(
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* *unbind/detach */
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_texture_unbind(fx->dof_near_coc_final_buffer);
@@ -1249,7 +1285,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass5, interface->medium_blurred_uniform, fx->dof_near_coc_buffer);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(dof_shader_pass5, interface->depth_uniform, fx->depth_buffer);
/* if this is the last pass, prepare for rendering on the frambuffer */
@@ -1260,7 +1297,8 @@ bool GPU_fx_do_composite_pass(
GPU_texture_unbind(fx->dof_near_coc_buffer);
GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
/* may not be attached, in that case this just returns */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index c8d5d92b66b..1fb1e239310 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -38,8 +38,6 @@
#include <string.h>
-#include "GPU_glew.h"
-
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
@@ -853,32 +851,6 @@ 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! */
- if (textarget == GL_TEXTURE_2D &&
- ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) ||
- is_over_resolution_limit(textarget, rectw, recth)))
- {
- rectw = smaller_power_of_2_limit(rectw);
- recth = smaller_power_of_2_limit(recth);
-
- if (use_high_bit_depth) {
- ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
- IMB_scaleImBuf(ibuf, rectw, recth);
-
- frect = ibuf->rect_float;
- }
- else {
- ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
- IMB_scaleImBuf(ibuf, rectw, recth);
-
- rect = ibuf->rect;
- }
- }
-#endif
-
/* create image */
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
@@ -1203,13 +1175,7 @@ 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
- {
+ if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) {
int x_limit = smaller_power_of_2_limit(ibuf->x);
int y_limit = smaller_power_of_2_limit(ibuf->y);
@@ -1438,31 +1404,40 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
if (smoke_has_colors(sds->fluid)) {
float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture");
smoke_get_rgba(sds->fluid, data, 0);
- sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data);
+ sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], data, NULL);
MEM_freeN(data);
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_density(sds->fluid));
+ sds->tex = GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1,
+ GPU_R8, smoke_get_density(sds->fluid), NULL);
}
- sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_flame(sds->fluid)) : NULL;
+ sds->tex_flame = (smoke_has_fuel(sds->fluid)) ?
+ GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1,
+ GPU_R8, smoke_get_flame(sds->fluid), NULL) :
+ NULL;
}
else if (!sds->tex && highres) {
/* rgba texture for color + density */
if (smoke_turbulence_has_colors(sds->wt)) {
float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture");
smoke_turbulence_get_rgba(sds->wt, data, 0);
- sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data);
+ sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], data, NULL);
MEM_freeN(data);
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_density(sds->wt));
+ sds->tex = GPU_texture_create_3D_custom(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1,
+ GPU_R8, smoke_turbulence_get_density(sds->wt), NULL);
}
- sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_flame(sds->wt)) : NULL;
+ sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ?
+ GPU_texture_create_3D_custom(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1,
+ GPU_R8, smoke_turbulence_get_flame(sds->wt), NULL):
+ NULL;
}
- sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, sds->shadow);
+ sds->tex_shadow = GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1,
+ GPU_R8, sds->shadow, NULL);
}
#else // WITH_SMOKE
(void)highres;
@@ -2184,7 +2159,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
int count = 0;
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
if (base->object->type != OB_LAMP)
continue;
@@ -2343,7 +2318,7 @@ void GPU_state_init(void)
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
-void GPU_enable_program_point_size()
+void GPU_enable_program_point_size(void)
{
#ifdef __APPLE__
/* TODO: remove this when we switch to core profile */
@@ -2353,7 +2328,7 @@ void GPU_enable_program_point_size()
#endif
}
-void GPU_disable_program_point_size()
+void GPU_disable_program_point_size(void)
{
#ifdef __APPLE__
/* TODO: remove this when we switch to core profile */
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e8fd4b8b8b1..d7ed65e853e 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -69,6 +69,8 @@ static struct GPUGlobal {
GLint maxtexsize;
GLint maxcubemapsize;
GLint maxtextures;
+ GLint maxubosize;
+ GLint maxubobinds;
bool extdisabled;
int colordepth;
int samples_color_texture_max;
@@ -121,6 +123,16 @@ int GPU_max_cube_map_size(void)
return GG.maxcubemapsize;
}
+int GPU_max_ubo_binds(void)
+{
+ return GG.maxubobinds;
+}
+
+int GPU_max_ubo_size(void)
+{
+ return GG.maxubosize;
+}
+
void GPU_get_dfdy_factors(float fac[2])
{
copy_v2_v2(fac, GG.dfdyfactors);
@@ -154,6 +166,9 @@ void gpu_extensions_init(void)
else
GG.max_anisotropy = 1.0f;
+ glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &GG.maxubobinds);
+ glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
+
GLint r, g, b;
glGetIntegerv(GL_RED_BITS, &r);
glGetIntegerv(GL_GREEN_BITS, &g);
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index ec1471744fa..1efc451f4a8 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -54,7 +54,7 @@ struct GPUFrameBuffer {
static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
{
- const char *format = "GPUFrameBuffer: framebuffer status %s";
+ const char *format = "GPUFrameBuffer: framebuffer status %s\n";
const char *err = "unknown";
#define format_status(X) \
@@ -260,6 +260,43 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
glPushMatrix();
}
+void GPU_framebuffer_bind(GPUFrameBuffer *fb)
+{
+ int numslots = 0, i;
+ GLenum attachments[4];
+ GLenum readattachement = 0;
+ GPUTexture *tex;
+
+ for (i = 0; i < 4; i++) {
+ if (fb->colortex[i]) {
+ attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
+ tex = fb->colortex[i];
+
+ if (!readattachement)
+ readattachement = GL_COLOR_ATTACHMENT0 + i;
+
+ numslots++;
+ }
+ }
+
+ /* bind framebuffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+
+ if (numslots == 0) {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ tex = fb->depthtex;
+ }
+ else {
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffers(numslots, attachments);
+ glReadBuffer(readattachement);
+ }
+
+ glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+ GG.currentfb = fb->object;
+}
+
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
{
@@ -283,7 +320,6 @@ void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
/* push matrices and set default viewport and matrix */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
GG.currentfb = fb->object;
- GG.currentfb = fb->object;
}
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
@@ -453,7 +489,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
return NULL;
}
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
+ ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, samples, err_out);
if (!ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 817756a3088..7a6b1ff6c70 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -32,6 +32,7 @@
#include "BLI_sys_types.h"
#include "GPU_init_exit.h" /* interface */
#include "GPU_immediate.h"
+#include "GPU_batch.h"
#include "BKE_global.h"
#include "intern/gpu_codegen.h"
@@ -59,6 +60,8 @@ void GPU_init(void)
if (G.debug & G_DEBUG_GPU)
gpu_debug_init();
+ gpu_batch_init();
+
immInit();
}
@@ -68,6 +71,8 @@ void GPU_exit(void)
{
immDestroy();
+ gpu_batch_exit();
+
if (G.debug & G_DEBUG_GPU)
gpu_debug_exit();
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 56b7af787e7..9e08f629bcb 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -609,7 +609,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
GPU_link(mat, "lamp_visibility_spot",
GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob),
- GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob),
+ GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTBLEND, lamp->ob),
inpr, visifac, &visifac);
}
@@ -1016,7 +1016,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
{
- Base *base;
+ BaseLegacy *base;
Scene *sce_iter;
for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) {
@@ -2369,6 +2369,11 @@ static void gpu_lamp_shadow_free(GPULamp *lamp)
}
}
+static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size)
+{
+ return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL);
+}
+
GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
{
Lamp *la;
@@ -2415,7 +2420,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
}
/* Shadow color map */
- lamp->tex = GPU_texture_create_vsm_shadow_map(lamp->size, NULL);
+ lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
if (!lamp->tex) {
gpu_lamp_shadow_free(lamp);
return lamp;
@@ -2438,7 +2443,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
+ lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
if (!lamp->blurtex) {
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
index 19ff856b688..855ccaa4999 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -70,12 +70,12 @@ static MatrixState state; /* TODO(merwin): make part of GPUContext, alongside im
#define Projection3D state.ProjectionMatrix3D
#define Projection2D state.ProjectionMatrix2D
-void gpuMatrixInit()
+void gpuMatrixInit(void)
{
memset(&state, 0, sizeof(MatrixState));
}
-void gpuMatrixBegin2D()
+void gpuMatrixBegin2D(void)
{
state.mode = MATRIX_MODE_2D;
state.top = 0;
@@ -83,7 +83,7 @@ void gpuMatrixBegin2D()
gpuOrtho2D(-1.0f, +1.0f, -1.0f, +1.0f); // or identity?
}
-void gpuMatrixBegin3D()
+void gpuMatrixBegin3D(void)
{
state.mode = MATRIX_MODE_3D;
state.top = 0;
@@ -92,7 +92,7 @@ void gpuMatrixBegin3D()
}
#if SUPPORT_LEGACY_MATRIX
-void gpuMatrixBegin3D_legacy()
+void gpuMatrixBegin3D_legacy(void)
{
/* copy top matrix from each legacy stack into new fresh stack */
state.mode = MATRIX_MODE_3D;
@@ -103,7 +103,7 @@ void gpuMatrixBegin3D_legacy()
}
#endif
-void gpuMatrixEnd()
+void gpuMatrixEnd(void)
{
state.mode = MATRIX_MODE_INACTIVE;
}
@@ -133,7 +133,7 @@ static void checkmat(cosnt float *m)
#endif
-void gpuPushMatrix()
+void gpuPushMatrix(void)
{
BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
BLI_assert(state.top < MATRIX_STACK_DEPTH);
@@ -144,7 +144,7 @@ void gpuPushMatrix()
copy_m3_m3(ModelView2D, state.ModelViewStack2D[state.top - 1]);
}
-void gpuPopMatrix()
+void gpuPopMatrix(void)
{
BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
BLI_assert(state.top > 0);
@@ -168,7 +168,7 @@ void gpuLoadMatrix2D(const float m[3][3])
state.dirty = true;
}
-void gpuLoadIdentity()
+void gpuLoadIdentity(void)
{
switch (state.mode) {
case MATRIX_MODE_3D:
@@ -281,7 +281,7 @@ void gpuScale3fv(const float vec[3])
void gpuMultMatrix3D(const float m[4][4])
{
BLI_assert(state.mode == MATRIX_MODE_3D);
- mul_m4_m4_pre(ModelView3D, m);
+ mul_m4_m4_post(ModelView3D, m);
CHECKMAT(ModelView3D);
state.dirty = true;
}
@@ -289,7 +289,7 @@ void gpuMultMatrix3D(const float m[4][4])
void gpuMultMatrix2D(const float m[3][3])
{
BLI_assert(state.mode == MATRIX_MODE_2D);
- mul_m3_m3_pre(ModelView2D, m);
+ mul_m3_m3_post(ModelView2D, m);
CHECKMAT(ModelView2D);
state.dirty = true;
}
@@ -622,7 +622,7 @@ const float *gpuGetNormalMatrix(float m[3][3])
m = temp3;
}
- copy_m3_m4(m, gpuGetModelViewMatrix3D(NULL));
+ copy_m3_m4(m, (const float (*)[4])gpuGetModelViewMatrix3D(NULL));
invert_m3(m);
transpose_m3(m);
@@ -695,7 +695,15 @@ void gpuBindMatrices(GLuint program)
state.dirty = false;
}
-bool gpuMatricesDirty()
+bool gpuMatricesDirty(void)
{
return state.dirty;
}
+
+#if SUPPORT_LEGACY_MATRIX
+void gpuMatrixUpdate_legacy(void)
+{
+ BLI_assert(state.mode == MATRIX_MODE_INACTIVE);
+ state.dirty = true;
+}
+#endif
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 4fd8ab0d8b4..295182b3153 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -37,6 +37,7 @@
#include "GPU_debug.h"
#include "GPU_extensions.h"
#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
#include "GPU_texture.h"
#include "gpu_shader_private.h"
@@ -48,6 +49,8 @@
/* 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_checker_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[];
extern char datatoc_gpu_shader_2D_vert_glsl[];
@@ -67,8 +70,16 @@ 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_3D_passthrough_vert_glsl[];
extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_vert_glsl[];
+extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[];
+
+extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
+extern char datatoc_gpu_shader_3D_groundline_geom_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[];
@@ -94,6 +105,8 @@ extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[];
extern char datatoc_gpu_shader_edges_overlay_frag_glsl[];
extern char datatoc_gpu_shader_text_vert_glsl[];
extern char datatoc_gpu_shader_text_frag_glsl[];
+extern char datatoc_gpu_shader_keyframe_diamond_vert_glsl[];
+extern char datatoc_gpu_shader_keyframe_diamond_frag_glsl[];
extern char datatoc_gpu_shader_fire_frag_glsl[];
extern char datatoc_gpu_shader_smoke_vert_glsl[];
@@ -512,11 +525,24 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
return glGetUniformLocation(shader->program, name);
}
+int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+
+ return glGetUniformBlockIndex(shader->program, name);
+}
+
void *GPU_shader_get_interface(GPUShader *shader)
{
return shader->uniform_interface;
}
+/* Clement : Temp */
+int GPU_shader_get_program(GPUShader *shader)
+{
+ return (int)shader->program;
+}
+
void GPU_shader_set_interface(GPUShader *shader, void *interface)
{
shader->uniform_interface = interface;
@@ -564,6 +590,17 @@ void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int ou
}
}
+void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
+{
+ int bindpoint = GPU_uniformbuffer_bindpoint(ubo);
+
+ if (location == -1) {
+ return;
+ }
+
+ glUniformBlockBinding(shader->program, location, bindpoint);
+}
+
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
{
int number = GPU_texture_bound_number(tex);
@@ -615,6 +652,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_SMOKE_COBA] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
[GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl, datatoc_gpu_shader_text_frag_glsl },
+ [GPU_SHADER_KEYFRAME_DIAMOND] = { datatoc_gpu_shader_keyframe_diamond_vert_glsl,
+ datatoc_gpu_shader_keyframe_diamond_frag_glsl },
[GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { datatoc_gpu_shader_edges_front_back_persp_vert_glsl,
/* this version is */ datatoc_gpu_shader_flat_color_frag_glsl,
/* magical but slooow */ datatoc_gpu_shader_edges_front_back_persp_geom_glsl },
@@ -625,6 +664,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_EDGES_OVERLAY] = { datatoc_gpu_shader_edges_overlay_vert_glsl,
datatoc_gpu_shader_edges_overlay_frag_glsl,
datatoc_gpu_shader_edges_overlay_geom_glsl },
+ [GPU_SHADER_SIMPLE_LIGHTING] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_simple_lighting_frag_glsl },
[GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_image_vert_glsl,
datatoc_gpu_shader_image_mask_uniform_color_frag_glsl },
@@ -635,8 +675,9 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl,
datatoc_gpu_shader_image_depth_linear_frag_glsl },
- [GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl,
- datatoc_gpu_shader_image_interlace_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_interlace_frag_glsl },
+ [GPU_SHADER_2D_CHECKER] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_checker_frag_glsl },
[GPU_SHADER_2D_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_2D_FLAT_COLOR] = { datatoc_gpu_shader_2D_flat_color_vert_glsl,
@@ -651,9 +692,17 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl,
datatoc_gpu_shader_3D_smooth_color_frag_glsl },
[GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl },
+
+ [GPU_SHADER_3D_GROUNDPOINT] = { datatoc_gpu_shader_3D_groundpoint_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_GROUNDLINE] = { datatoc_gpu_shader_3D_passthrough_vert_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ datatoc_gpu_shader_3D_groundline_geom_glsl },
[GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl,
datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+
[GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
{ datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
[GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] =
@@ -683,11 +732,17 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] =
{ datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl,
datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl },
+
+ [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { datatoc_gpu_shader_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] =
+ { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
};
if (builtin_shaders[shader] == NULL) {
/* just a few special cases */
- const char *defines = (shader == GPU_SHADER_SMOKE_COBA) ? "#define USE_COBA;\n" : NULL;
+ const char *defines = (shader == GPU_SHADER_SMOKE_COBA) ? "#define USE_COBA;\n" :
+ (shader == GPU_SHADER_SIMPLE_LIGHTING) ? "#define USE_NORMALS;\n" : NULL;
const GPUShaderStages *stages = builtin_shader_stages + shader;
@@ -699,6 +754,14 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
stages = &legacy_fancy_edges;
}
+ if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP && !GLEW_VERSION_3_2) {
+ /* TODO: remove after switch to core profile (maybe) */
+ static const GPUShaderStages legacy_fancy_edges =
+ { datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl,
+ datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl };
+ stages = &legacy_fancy_edges;
+ }
+
/* common case */
builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom,
NULL, defines, 0, 0, 0);
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 6956a815ac5..3513250993e 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -49,9 +49,8 @@ static struct GPUTextureGlobal {
} GG = {NULL, NULL, NULL};
/* GPUTexture */
-
struct GPUTexture {
- int w, h; /* width/height */
+ int w, h, d; /* width/height/depth */
int number; /* number for multitexture binding */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
@@ -62,42 +61,162 @@ struct GPUTexture {
GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
int fb_attachment; /* slot the texture is attached to */
- int depth; /* is a depth texture? if 3D how deep? */
+ bool depth; /* is a depth texture? */
};
-static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
+static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, GLenum *format, bool *is_depth)
{
- unsigned char *pixels, *p;
- const float *fp = fpixels;
- const int len = 4 * length;
+ if (data_type == GPU_DEPTH_COMPONENT24 ||
+ data_type == GPU_DEPTH_COMPONENT16 ||
+ data_type == GPU_DEPTH_COMPONENT32F)
+ {
+ *is_depth = true;
+ *format = GL_DEPTH_COMPONENT;
+ }
+ else {
+ *is_depth = false;
+
+ switch (components) {
+ case 1: *format = GL_RED; break;
+ case 2: *format = GL_RG; break;
+ case 3: *format = GL_RGB; break;
+ case 4: *format = GL_RGBA; break;
+ default: break;
+ }
+ }
- p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
+ /* You can add any of the available type to this list
+ * For available types see GPU_texture.h */
+ switch (data_type) {
+ /* Formats texture & renderbuffer */
+ case GPU_RGBA16F: return GL_RGBA16F;
+ case GPU_RG32F: return GL_RG32F;
+ case GPU_RG16F: return GL_RG16F;
+ case GPU_RGBA8: return GL_RGBA8;
+ case GPU_R8: return GL_R8;
+ /* Special formats texture & renderbuffer */
+ /* ** Add Format here **/
+ /* Texture only format */
+ /* ** Add Format here **/
+ /* Special formats texture only */
+ /* ** Add Format here **/
+ /* Depth Formats */
+ case GPU_DEPTH_COMPONENT32F: return GL_DEPTH_COMPONENT32F;
+ case GPU_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT24;
+ case GPU_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT16;
+ default:
+ fprintf(stderr, "Texture format incorrect or unsupported\n");
+ return 0;
+ }
+}
- for (int a = 0; a < len; a++, p++, fp++)
- *p = FTOCHAR((*fp));
+static float *GPU_texture_3D_rescale(GPUTexture *tex, int w, int h, int d, int channels, const float *fpixels)
+{
+ const unsigned int xf = w / tex->w, yf = h / tex->h, zf = d / tex->d;
+ float *nfpixels = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->d, "GPUTexture Rescaled 3Dtex");
- return pixels;
+ if (nfpixels) {
+ GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+ for (unsigned k = 0; k < tex->d; k++) {
+ for (unsigned j = 0; j < tex->h; j++) {
+ for (unsigned i = 0; i < tex->w; i++) {
+ /* obviously doing nearest filtering here,
+ * it's going to be slow in any case, let's not make it worse */
+ float xb = i * xf;
+ float yb = j * yf;
+ float zb = k * zf;
+ unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+ unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+
+ if (channels == 4) {
+ nfpixels[offset * 4] = fpixels[offset_orig * 4];
+ nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+ nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+ nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+ }
+ else
+ nfpixels[offset] = fpixels[offset_orig];
+ }
+ }
+ }
+ }
+
+ return nfpixels;
}
-static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
+/* This tries to allocate video memory for a given texture
+ * If alloc fails, lower the resolution until it fits. */
+static bool GPU_texture_try_alloc(
+ GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, int channels,
+ bool try_rescale, const float *fpixels, float **rescaled_fpixels)
{
- void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
+ int r_width;
- if (target == GL_TEXTURE_1D)
- glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
- else
- glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
-
- MEM_freeN(pixels);
+ switch (proxy) {
+ case GL_PROXY_TEXTURE_1D:
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL);
+ break;
+ case GL_PROXY_TEXTURE_2D:
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL);
+ break;
+ case GL_PROXY_TEXTURE_3D:
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL);
+ break;
+ }
+
+ glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &r_width);
+
+ if (r_width == 0 && try_rescale) {
+ const int w = tex->w, h = tex->h, d = tex->d;
+
+ /* Find largest texture possible */
+ while (r_width == 0) {
+ tex->w /= 2;
+ tex->h /= 2;
+ tex->d /= 2;
+
+ /* really unlikely to happen but keep this just in case */
+ if (tex->w == 0) break;
+ if (tex->h == 0 && proxy != GL_PROXY_TEXTURE_1D) break;
+ if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break;
+
+ if (proxy == GL_PROXY_TEXTURE_1D)
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_2D)
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_3D)
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL);
+
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ }
+
+ /* Rescale */
+ if (r_width > 0) {
+ switch (proxy) {
+ case GL_PROXY_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_2D:
+ /* Do nothing for now */
+ return false;
+ case GL_PROXY_TEXTURE_3D:
+ *rescaled_fpixels = GPU_texture_3D_rescale(tex, w, h, d, channels, fpixels);
+ return (bool)*rescaled_fpixels;
+ }
+ }
+ }
+
+ return (r_width > 0);
}
static GPUTexture *GPU_texture_create_nD(
- int w, int h, int n, const float *fpixels, int depth,
- GPUHDRType hdr_type, int components, int samples,
- char err_out[256])
+ int w, int h, int d, int n, const float *fpixels,
+ GPUTextureFormat data_type, int components, int samples,
+ const bool can_rescale, char err_out[256])
{
- GLenum type, format, internalformat;
- void *pixels = NULL;
+ GLenum format, internalformat, proxy;
+ float *rescaled_fpixels = NULL;
+ const float *pix;
+ bool valid;
if (samples) {
CLAMP_MAX(samples, GPU_max_color_texture_samples());
@@ -106,121 +225,99 @@ static GPUTexture *GPU_texture_create_nD(
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->w = w;
tex->h = h;
+ tex->d = d;
tex->number = -1;
tex->refcount = 1;
- tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
- tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
- tex->depth = depth;
+
+ if (n == 1) {
+ if (h == 0)
+ tex->target_base = tex->target = GL_TEXTURE_1D;
+ else
+ tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY;
+ }
+ else if (n == 2) {
+ if (d == 0)
+ tex->target_base = tex->target = GL_TEXTURE_2D;
+ else
+ tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY;
+ }
+ else if (n == 3) {
+ tex->target_base = tex->target = GL_TEXTURE_3D;
+ }
+
tex->fb_attachment = -1;
+ if (samples && n == 2 && d == 0)
+ tex->target = GL_TEXTURE_2D_MULTISAMPLE;
+
+ internalformat = GPU_texture_get_format(components, data_type, &format, &tex->depth);
+
+ /* Generate Texture object */
glGenTextures(1, &tex->bindcode);
if (!tex->bindcode) {
- if (err_out) {
+ if (err_out)
BLI_snprintf(err_out, 256, "GPUTexture: texture create failed");
- }
- else {
+ else
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);
- if (depth) {
- type = GL_UNSIGNED_BYTE;
- format = GL_DEPTH_COMPONENT;
- internalformat = GL_DEPTH_COMPONENT;
+ /* Check if texture fit in VRAM */
+ if (d > 0) {
+ proxy = GL_PROXY_TEXTURE_3D;
+ }
+ else if (h > 0) {
+ proxy = GL_PROXY_TEXTURE_2D;
}
else {
- type = GL_FLOAT;
-
- if (components == 4) {
- format = GL_RGBA;
- switch (hdr_type) {
- case GPU_HDR_NONE:
- internalformat = GL_RGBA8;
- break;
- /* the following formats rely on ARB_texture_float or OpenGL 3.0 */
- case GPU_HDR_HALF_FLOAT:
- internalformat = GL_RGBA16F_ARB;
- break;
- case GPU_HDR_FULL_FLOAT:
- internalformat = GL_RGBA32F_ARB;
- break;
- default:
- break;
- }
- }
- else if (components == 2) {
- /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
- format = GL_RG;
- switch (hdr_type) {
- case GPU_HDR_NONE:
- internalformat = GL_RG8;
- break;
- case GPU_HDR_HALF_FLOAT:
- internalformat = GL_RG16F;
- break;
- case GPU_HDR_FULL_FLOAT:
- internalformat = GL_RG32F;
- break;
- default:
- break;
- }
- }
-
- if (fpixels && hdr_type == GPU_HDR_NONE) {
- type = GL_UNSIGNED_BYTE;
- pixels = GPU_texture_convert_pixels(w * h, fpixels);
- }
+ proxy = GL_PROXY_TEXTURE_1D;
}
- if (tex->target == GL_TEXTURE_1D) {
- glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
+ valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, components, can_rescale, fpixels,
+ &rescaled_fpixels);
- if (fpixels) {
- glTexSubImage1D(tex->target, 0, 0, w, format, type,
- pixels ? pixels : fpixels);
+ if (!valid) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUTexture: texture alloc failed");
+ else
+ fprintf(stderr, "GPUTexture: texture alloc failed. Not enough Video Memory.");
+ GPU_texture_free(tex);
+ return NULL;
+ }
- if (tex->w > w) {
- GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
- }
- }
+ /* Upload Texture */
+ pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels;
+
+ if (tex->target == GL_TEXTURE_1D) {
+ glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, GL_FLOAT, pix);
}
- else {
+ else if (tex->target == GL_TEXTURE_1D_ARRAY ||
+ tex->target == GL_TEXTURE_2D ||
+ tex->target == GL_TEXTURE_2D_MULTISAMPLE)
+ {
if (samples) {
glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+ if (pix)
+ glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, GL_FLOAT, pix);
}
else {
- glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
- format, type, NULL);
- }
-
- if (fpixels) {
- glTexSubImage2D(tex->target, 0, 0, 0, w, h,
- format, type, pixels ? pixels : fpixels);
-
- if (tex->w > w)
- GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
- if (tex->h > h)
- GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
+ glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, pix);
}
}
+ else {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, pix);
+ }
- if (pixels)
- MEM_freeN(pixels);
+ if (rescaled_fpixels)
+ MEM_freeN(rescaled_fpixels);
- if (depth) {
+ /* Texture Parameters */
+ if (tex->depth) {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
@@ -232,128 +329,14 @@ static GPUTexture *GPU_texture_create_nD(
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- if (tex->target_base != GL_TEXTURE_1D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ if (n > 1) {
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
- else
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
- return tex;
-}
-
-
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
-{
- GLenum type, format, internalformat;
- void *pixels = NULL;
-
- GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
- tex->depth = depth;
- tex->number = -1;
- tex->refcount = 1;
- tex->target = GL_TEXTURE_3D;
- tex->target_base = GL_TEXTURE_3D;
-
- glGenTextures(1, &tex->bindcode);
-
- if (!tex->bindcode) {
- fprintf(stderr, "GPUTexture: texture create failed");
- GPU_texture_free(tex);
- return NULL;
- }
-
- tex->number = 0;
- glBindTexture(tex->target, tex->bindcode);
-
- type = GL_FLOAT;
- if (channels == 4) {
- format = GL_RGBA;
- internalformat = GL_RGBA8;
- }
- else {
- format = GL_RED;
- internalformat = GL_INTENSITY8;
+ if (n > 2) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
- /* 3D textures are quite heavy, test if it's possible to create them first */
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
-
- bool rescale = false;
- int r_width;
-
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
-
- while (r_width == 0) {
- rescale = true;
- tex->w /= 2;
- tex->h /= 2;
- tex->depth /= 2;
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
- }
-
- /* really unlikely to happen but keep this just in case */
- tex->w = max_ii(tex->w, 1);
- tex->h = max_ii(tex->h, 1);
- tex->depth = max_ii(tex->depth, 1);
-
-#if 0
- if (fpixels)
- pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
-#endif
-
- /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
- * for gooseberry */
- if (rescale && fpixels) {
- /* FIXME: should these be floating point? */
- const unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
- float *tex3d = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->depth, "tex3d");
-
- GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
-
- for (unsigned k = 0; k < tex->depth; k++) {
- for (unsigned j = 0; j < tex->h; j++) {
- for (unsigned i = 0; i < tex->w; i++) {
- /* obviously doing nearest filtering here,
- * it's going to be slow in any case, let's not make it worse */
- float xb = i * xf;
- float yb = j * yf;
- float zb = k * zf;
- unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
- unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
-
- if (channels == 4) {
- tex3d[offset * 4] = fpixels[offset_orig * 4];
- tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
- tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
- tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
- }
- else
- tex3d[offset] = fpixels[offset_orig];
- }
- }
- }
-
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
-
- MEM_freeN(tex3d);
- }
- 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);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- if (pixels)
- MEM_freeN(pixels);
-
GPU_texture_unbind(tex);
return tex;
@@ -464,114 +447,64 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
}
-GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, 0, 0, 1, pixels, GPU_RGBA8, 4, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
+GPUTexture *GPU_texture_create_1D_custom(
+ int w, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, 0, 0, 1, pixels, data_type, channels, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_2D_multisample(
- int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, GPU_RGBA8, 4, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
+GPUTexture *GPU_texture_create_2D_custom(
+ int w, int h, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, data_type, channels, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
- return tex;
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, int samples, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, GPU_RGBA8, 4, samples, false, err_out);
}
-/**
- * A shadow map for VSM needs two components (depth and depth^2)
- */
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
+GPUTexture *GPU_texture_create_2D_array(int w, int h, int d, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- GPU_texture_unbind(tex);
- }
-
- return tex;
+ return GPU_texture_create_nD(w, h, d, 2, pixels, GPU_RGBA8, 4, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
+GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- if (repeat) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- GPU_texture_unbind(tex);
- }
-
- return tex;
+ return GPU_texture_create_nD(w, h, d, 3, pixels, GPU_RGBA8, 4, 0, true, err_out);
}
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+GPUTexture *GPU_texture_create_3D_custom(int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ return GPU_texture_create_nD(w, h, d, 3, pixels, data_type, channels, 0, true, err_out);
+}
- GPU_texture_unbind(tex);
- }
+GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, 0, false, err_out);
+}
- return tex;
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, samples, false, err_out);
}
void GPU_invalid_tex_init(void)
{
const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
- GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
- GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
+ GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL);
+ GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, color, NULL);
}
void GPU_invalid_tex_bind(int mode)
@@ -624,7 +557,13 @@ void GPU_texture_bind(GPUTexture *tex, int number)
else
GPU_invalid_tex_bind(tex->target_base);
- glEnable(tex->target_base); /* TODO: remove this line once we're using GLSL everywhere */
+ /* TODO: remove this lines once we're using GLSL everywhere */
+ GLenum target = tex->target_base;
+ if (tex->target_base == GL_TEXTURE_1D_ARRAY)
+ target = GL_TEXTURE_2D;
+ if (tex->target_base == GL_TEXTURE_2D_ARRAY)
+ target = GL_TEXTURE_3D;
+ glEnable(target);
if (number != 0)
glActiveTexture(GL_TEXTURE0);
@@ -646,7 +585,14 @@ void GPU_texture_unbind(GPUTexture *tex)
glActiveTexture(GL_TEXTURE0 + tex->number);
glBindTexture(tex->target_base, 0);
- glDisable(tex->target_base); /* TODO: remove this line */
+
+ /* TODO: remove this lines */
+ GLenum target = tex->target_base;
+ if (tex->target_base == GL_TEXTURE_1D_ARRAY)
+ target = GL_TEXTURE_2D;
+ if (tex->target_base == GL_TEXTURE_2D_ARRAY)
+ target = GL_TEXTURE_3D;
+ glDisable(target);
if (tex->number != 0)
glActiveTexture(GL_TEXTURE0);
@@ -659,7 +605,7 @@ int GPU_texture_bound_number(GPUTexture *tex)
return tex->number;
}
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
{
if (tex->number >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
@@ -672,13 +618,54 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
if (tex->number != 0)
glActiveTexture(GL_TEXTURE0 + tex->number);
- if (tex->depth) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE);
+ /* TODO viewport: use GL_COMPARE_REF_TO_TEXTURE after we switch to core profile */
+ if (tex->depth)
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, use_compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE);
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0);
+}
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
+{
+ if (tex->number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
}
+ if (tex->number == -1)
+ return;
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+
GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0);
+}
+
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat)
+{
+ if (tex->number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
+ }
+
+ if (tex->number == -1)
+ return;
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+
+ GLenum repeat = use_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
+ if (tex->target_base != GL_TEXTURE_1D)
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
+ if (tex->target_base == GL_TEXTURE_3D)
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
if (tex->number != 0)
glActiveTexture(GL_TEXTURE0);
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
new file mode 100644
index 00000000000..76aa1a8226f
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -0,0 +1,105 @@
+/*
+ * ***** 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): Clement Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_uniformbuffer.c
+ * \ingroup gpu
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+#include "GPU_uniformbuffer.h"
+
+struct GPUUniformBuffer {
+ int size; /* in bytes */
+ GLuint bindcode; /* opengl identifier for UBO */
+ int bindpoint; /* current binding point */
+};
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256])
+{
+ GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBuffer), "GPUUniformBuffer");
+ ubo->size = size;
+
+ /* Generate Buffer object */
+ glGenBuffers(1, &ubo->bindcode);
+
+ if (!ubo->bindcode) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed");
+ GPU_uniformbuffer_free(ubo);
+ return NULL;
+ }
+
+ if (ubo->size > GPU_max_ubo_size()) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big");
+ GPU_uniformbuffer_free(ubo);
+ return NULL;
+ }
+
+ glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
+ glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ return ubo;
+}
+
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
+{
+ glDeleteBuffers(1, &ubo->bindcode);
+ MEM_freeN(ubo);
+}
+
+void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+{
+ glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number)
+{
+ if (number >= GPU_max_ubo_binds()) {
+ fprintf(stderr, "Not enough UBO slots.\n");
+ return;
+ }
+
+ if (ubo->bindcode != 0) {
+ glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode);
+ }
+
+ ubo->bindpoint = number;
+}
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo)
+{
+ return ubo->bindpoint;
+} \ No newline at end of file
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 2f91adde133..62ba06b7a0a 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -31,10 +31,20 @@
* System that manages viewport drawing.
*/
+#include <string.h>
+
+#include "BLI_rect.h"
+#include "BLI_string.h"
+
+#include "DNA_vec_types.h"
+
+#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_immediate.h"
-#include "GPU_viewport.h"
#include "GPU_texture.h"
+#include "GPU_viewport.h"
+
+#include "DRW_engine.h"
#include "MEM_guardedalloc.h"
@@ -43,26 +53,235 @@ struct GPUViewport {
/* debug */
GPUTexture *debug_depth;
- int debug_width, debug_height;
+ int size[2];
+
+ /* Viewport Buffer Storage */
+ /* TODO indentify to what engine conf are theses buffers */
+ DefaultFramebufferList *fbl;
+ DefaultTextureList *txl;
+ DefaultPassList *psl;
+ StorageList *stl;
+
+ char engine_name[32];
};
+static void GPU_viewport_buffers_free(GPUViewport *viewport);
+static void GPU_viewport_passes_free(GPUViewport *viewport);
+static void GPU_viewport_storage_free(GPUViewport *viewport);
+
GPUViewport *GPU_viewport_create(void)
{
GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
+ viewport->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList");
+ viewport->txl = MEM_callocN(sizeof(TextureList), "TextureList");
+ viewport->psl = MEM_callocN(sizeof(PassList), "PassList");
+ viewport->stl = MEM_callocN(sizeof(StorageList), "StorageList");
+ viewport->size[0] = viewport->size[1] = -1;
+
return viewport;
}
+void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str)
+{
+ *fbs = viewport->fbl;
+ *txs = viewport->txl;
+ *pss = viewport->psl;
+ *str = viewport->stl;
+}
+
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine)
+{
+ /* add one pixel because of scissor test */
+ int rect_w = BLI_rcti_size_x(rect) + 1, rect_h = BLI_rcti_size_y(rect) + 1;
+
+#ifndef WITH_VIEWPORT_CACHE_TEST
+ /* TODO for testing only, we need proper cache invalidation */
+ GPU_viewport_passes_free(viewport);
+#endif
+
+ if (!STREQ(engine, viewport->engine_name)) {
+ GPU_viewport_storage_free(viewport);
+ GPU_viewport_buffers_free(viewport);
+
+ BLI_strncpy(viewport->engine_name, engine, 32);
+ }
+
+ if (viewport->fbl->default_fb) {
+ if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) {
+ GPU_viewport_buffers_free(viewport);
+ }
+ }
+
+ if (!viewport->fbl->default_fb) {
+ bool ok = true;
+ viewport->size[0] = rect_w;
+ viewport->size[1] = rect_h;
+
+ viewport->fbl->default_fb = GPU_framebuffer_create();
+ if (!viewport->fbl->default_fb) {
+ ok = false;
+ goto cleanup;
+ }
+
+ /* Color */
+ /* No multi samples for now */
+ viewport->txl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
+ if (!viewport->txl->color) {
+ ok = false;
+ goto cleanup;
+ }
+
+ if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->color, 0)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ /* Depth */
+ viewport->txl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL);
+ if (!viewport->txl->depth) {
+ ok = false;
+ goto cleanup;
+ }
+ else if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->depth, 0)) {
+ ok = false;
+ goto cleanup;
+ }
+ else if (!GPU_framebuffer_check_valid(viewport->fbl->default_fb, NULL)) {
+ ok = false;
+ goto cleanup;
+ }
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ MEM_freeN(viewport);
+ return;
+ }
+
+ GPU_framebuffer_restore();
+ }
+
+ GPU_framebuffer_slots_bind(viewport->fbl->default_fb, 0);
+}
+
+static void draw_ofs_to_screen(GPUViewport *viewport)
+{
+ GPUTexture *color = viewport->txl->color;
+
+ const float w = (float)GPU_texture_width(color);
+ const float h = (float)GPU_texture_height(color);
+
+ 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);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+
+ GPU_texture_bind(color, 0);
+
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
+
+ immBegin(GL_QUADS, 4);
+
+ immAttrib2f(texcoord, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, 0.0f);
+
+ immAttrib2f(texcoord, 1.0f, 0.0f);
+ immVertex2f(pos, w, 0.0f);
+
+ immAttrib2f(texcoord, 1.0f, 1.0f);
+ immVertex2f(pos, w, h);
+
+ immAttrib2f(texcoord, 0.0f, 1.0f);
+ immVertex2f(pos, 0.0f, h);
+
+ immEnd();
+
+ GPU_texture_unbind(color);
+
+ immUnbindProgram();
+}
+
+void GPU_viewport_unbind(GPUViewport *viewport)
+{
+ if (viewport->fbl->default_fb) {
+ GPU_framebuffer_texture_unbind(NULL, NULL);
+ GPU_framebuffer_restore();
+
+ glEnable(GL_SCISSOR_TEST);
+
+ /* This might be bandwidth limiting */
+ draw_ofs_to_screen(viewport);
+ }
+}
+
+static void GPU_viewport_buffers_free(GPUViewport *viewport)
+{
+ FramebufferList *fbl = (FramebufferList *)viewport->fbl;
+ TextureList *txl = (TextureList *)viewport->txl;
+ int i;
+ for (i = MAX_BUFFERS - 1; i > -1; --i) {
+ GPUFrameBuffer *fb = fbl->framebuffers[i];
+ if (fb) {
+ GPU_framebuffer_free(fb);
+ fbl->framebuffers[i] = NULL;
+ }
+ }
+ for (i = MAX_TEXTURES - 1; i > -1; --i) {
+ GPUTexture *tex = txl->textures[i];
+ if (tex) {
+ GPU_texture_free(tex);
+ txl->textures[i] = NULL;
+ }
+ }
+}
+
+static void GPU_viewport_storage_free(GPUViewport *viewport)
+{
+ StorageList *stl = (StorageList *)viewport->stl;
+
+ for (int i = MAX_STORAGE - 1; i > -1; --i) {
+ void *storage = stl->storage[i];
+ if (storage) {
+ MEM_freeN(storage);
+ stl->storage[i] = NULL;
+ }
+ }
+}
+
+static void GPU_viewport_passes_free(GPUViewport *viewport)
+{
+ PassList *psl = (PassList *)viewport->psl;
+ int i;
+
+ for (i = MAX_PASSES - 1; i > -1; --i) {
+ struct DRWPass *pass = psl->passes[i];
+ if (pass) {
+ DRW_pass_free(pass);
+ MEM_freeN(pass);
+ psl->passes[i] = NULL;
+ }
+ }
+}
+
void GPU_viewport_free(GPUViewport *viewport)
{
GPU_viewport_debug_depth_free(viewport);
- MEM_freeN(viewport);
+ GPU_viewport_buffers_free(viewport);
+ GPU_viewport_passes_free(viewport);
+ GPU_viewport_storage_free(viewport);
+
+ MEM_freeN(viewport->fbl);
+ MEM_freeN(viewport->txl);
+ MEM_freeN(viewport->psl);
+ MEM_freeN(viewport->stl);
}
/****************** debug ********************/
bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256])
{
- viewport->debug_depth = GPU_texture_create_2D(width, height, NULL, GPU_HDR_HALF_FLOAT, err_out);
+ viewport->debug_depth = GPU_texture_create_2D_custom(width, height, 4, GPU_RGBA16F, NULL, err_out);
return (viewport->debug_depth != NULL);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl
new file mode 100644
index 00000000000..f16fa21b342
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl
@@ -0,0 +1,16 @@
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ViewProjectionMatrix;
+
+layout(points) in;
+layout(line_strip, max_vertices = 2) out;
+
+void main()
+{
+ vec3 vert = gl_in[0].gl_Position.xyz;
+ gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0);
+ EmitVertex();
+ gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0);
+ EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl
new file mode 100644
index 00000000000..55f410eb25d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl
@@ -0,0 +1,11 @@
+
+/* Made to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ViewProjectionMatrix;
+
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * vec4(pos.xy, 0.0, 1.0);
+ gl_PointSize = 2.0;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl
new file mode 100644
index 00000000000..60793bf56b6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl
@@ -0,0 +1,8 @@
+
+/* Does Nothing */
+in vec3 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
index 32da3a99c63..58150c004e5 100644
--- a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
@@ -1,13 +1,27 @@
uniform mat4 ModelViewProjectionMatrix;
+#ifdef USE_NORMALS
+uniform mat3 NormalMatrix;
+#endif
#if __VERSION__ == 120
attribute vec3 pos;
+#ifdef USE_NORMALS
+ attribute vec3 nor;
+ varying vec3 normal;
+#endif
#else
in vec3 pos;
+#ifdef USE_NORMALS
+ in vec3 nor;
+ out vec3 normal;
+#endif
#endif
void main()
{
+#ifdef USE_NORMALS
+ normal = normalize(NormalMatrix * nor);
+#endif
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl
new file mode 100644
index 00000000000..3b24af916a0
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl
@@ -0,0 +1,24 @@
+
+uniform vec4 color1;
+uniform vec4 color2;
+uniform int size;
+
+#if __VERSION__ == 120
+ #define fragColor gl_FragColor
+#else
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ vec2 phase = mod(gl_FragCoord.xy, (size*2));
+
+ if ((phase.x > size && phase.y < size) ||
+ (phase.x < size && phase.y > size))
+ {
+ fragColor = color1;
+ }
+ else {
+ fragColor = color2;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl
new file mode 100644
index 00000000000..ba0ac29fb79
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+uniform float size;
+uniform float pixel_size;
+
+/* ---- Instanciated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 world_pos;
+in vec3 color;
+
+flat out vec4 finalColor;
+
+float mul_project_m4_v3_zfac(in vec3 co)
+{
+ return (ViewProjectionMatrix[0][3] * co.x) +
+ (ViewProjectionMatrix[1][3] * co.y) +
+ (ViewProjectionMatrix[2][3] * co.z) + ViewProjectionMatrix[3][3];
+}
+
+void main()
+{
+ float pix_size = mul_project_m4_v3_zfac(world_pos) * pixel_size;
+ vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+ gl_Position = ViewProjectionMatrix * vec4(world_pos + screen_pos * size * pix_size, 1.0);
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
new file mode 100644
index 00000000000..9ade68644fe
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
@@ -0,0 +1,18 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 color;
+in float size;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * size, 1.0);
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl
new file mode 100644
index 00000000000..eac167e8045
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
new file mode 100644
index 00000000000..43a7e42153a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
@@ -0,0 +1,38 @@
+
+#if __VERSION__ == 120
+ varying vec4 radii;
+ varying vec4 finalColor;
+ varying vec4 finalOutlineColor;
+ #define fragColor gl_FragColor
+#else
+ in vec4 radii;
+ in vec4 finalColor;
+ in vec4 finalOutlineColor;
+ out vec4 fragColor;
+#endif
+
+void main() {
+ vec2 quad = abs(gl_PointCoord - vec2(0.5));
+ float dist = quad.x + quad.y;
+
+// 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 mid_stroke = 0.5 * (radii[1] + radii[2]);
+
+ vec4 backgroundColor = vec4(finalColor.rgb, 0.0);
+
+ if (dist > mid_stroke)
+ fragColor = mix(finalOutlineColor, backgroundColor, smoothstep(radii[1], radii[0], dist));
+ else
+ fragColor = mix(finalColor, finalOutlineColor, smoothstep(radii[3], radii[2], dist));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
new file mode 100644
index 00000000000..69afefa685f
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
@@ -0,0 +1,44 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+const float pixel_fudge = sqrt(2.0);
+const float outline_width = 1.25 * pixel_fudge;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute float size;
+ attribute vec4 color;
+ attribute vec4 outlineColor;
+ varying vec4 finalColor;
+ varying vec4 finalOutlineColor;
+ varying vec4 radii;
+#else
+ in vec2 pos;
+ in float size;
+ in vec4 color;
+ in vec4 outlineColor;
+ out vec4 finalColor;
+ out vec4 finalOutlineColor;
+ out vec4 radii;
+#endif
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+ // pass through unchanged
+ gl_PointSize = size;
+ finalColor = color;
+ finalOutlineColor = outlineColor;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * gl_PointSize;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - pixel_fudge;
+ radii[2] = radius - outline_width;
+ radii[3] = radius - outline_width - pixel_fudge;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index aa583c5ecf8..0f3ffa8244b 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -3536,6 +3536,8 @@ void node_light_path(
out float is_transmission_ray,
out float ray_length,
out float ray_depth,
+ out float diffuse_depth,
+ out float glossy_depth,
out float transparent_depth,
out float transmission_depth)
{
@@ -3548,6 +3550,8 @@ void node_light_path(
is_transmission_ray = 0.0;
ray_length = 1.0;
ray_depth = 1.0;
+ diffuse_depth = 1.0;
+ glossy_depth = 1.0;
transparent_depth = 1.0;
transmission_depth = 1.0;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
new file mode 100644
index 00000000000..9828787fb04
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
@@ -0,0 +1,16 @@
+
+uniform vec4 color;
+uniform vec3 light;
+
+#if __VERSION__ == 120
+ varying vec3 normal;
+ #define fragColor gl_FragColor
+#else
+ in vec3 normal;
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ fragColor = color * max(0.0, dot(normalize(normal), light));
+}
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 52febe642a0..4164f5fa75d 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -77,6 +77,16 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha
const char *from_colorspace, const char *to_colorspace, bool predivide);
void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
const char *from_colorspace, const char *to_colorspace, bool predivide);
+void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
+void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
+void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
+void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace);
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace);
@@ -185,6 +195,8 @@ void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_proc
void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, float *pixel, int channels);
void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height,
int channels, bool predivide);
+void IMB_colormanagement_processor_apply_byte(struct ColormanageProcessor *cm_processor,
+ unsigned char *buffer, int width, int height, int channels);
void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor);
/* ** OpenGL drawing routines using GLSL for color space transform ** */
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index a45346279d9..48cba3e0800 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1555,21 +1555,25 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ
typedef struct ProcessorTransformThread {
ColormanageProcessor *cm_processor;
- float *buffer;
+ unsigned char *byte_buffer;
+ float *float_buffer;
int width;
int start_line;
int tot_line;
int channels;
bool predivide;
+ bool float_from_byte;
} ProcessorTransformThread;
typedef struct ProcessorTransformInit {
ColormanageProcessor *cm_processor;
- float *buffer;
+ unsigned char *byte_buffer;
+ float *float_buffer;
int width;
int height;
int channels;
bool predivide;
+ bool float_from_byte;
} ProcessorTransformInitData;
static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@@ -1577,17 +1581,24 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int
ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v;
ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v;
- int channels = init_data->channels;
- int width = init_data->width;
- bool predivide = init_data->predivide;
+ const int channels = init_data->channels;
+ const int width = init_data->width;
+ const bool predivide = init_data->predivide;
+ const bool float_from_byte = init_data->float_from_byte;
- size_t offset = ((size_t)channels) * start_line * width;
+ const size_t offset = ((size_t)channels) * start_line * width;
memset(handle, 0, sizeof(ProcessorTransformThread));
handle->cm_processor = init_data->cm_processor;
- handle->buffer = init_data->buffer + offset;
+ if (init_data->byte_buffer != NULL) {
+ /* TODO(serge): Offset might be different for byte and float buffers. */
+ handle->byte_buffer = init_data->byte_buffer + offset;
+ }
+ if (init_data->float_buffer != NULL) {
+ handle->float_buffer = init_data->float_buffer + offset;
+ }
handle->width = width;
@@ -1596,33 +1607,62 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int
handle->channels = channels;
handle->predivide = predivide;
+ handle->float_from_byte = float_from_byte;
}
static void *do_processor_transform_thread(void *handle_v)
{
ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v;
- float *buffer = handle->buffer;
- int channels = handle->channels;
- int width = handle->width;
- int height = handle->tot_line;
- bool predivide = handle->predivide;
-
- IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide);
+ unsigned char *byte_buffer = handle->byte_buffer;
+ float *float_buffer = handle->float_buffer;
+ const int channels = handle->channels;
+ const int width = handle->width;
+ const int height = handle->tot_line;
+ const bool predivide = handle->predivide;
+ const bool float_from_byte = handle->float_from_byte;
+
+ if (float_from_byte) {
+ IMB_buffer_float_from_byte(float_buffer, byte_buffer,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ true,
+ width, height, width, width);
+ IMB_colormanagement_processor_apply(handle->cm_processor,
+ float_buffer,
+ width, height, channels,
+ predivide);
+ }
+ else {
+ if (byte_buffer != NULL) {
+ IMB_colormanagement_processor_apply_byte(handle->cm_processor,
+ byte_buffer,
+ width, height, channels);
+ }
+ if (float_buffer != NULL) {
+ IMB_colormanagement_processor_apply(handle->cm_processor,
+ float_buffer,
+ width, height, channels,
+ predivide);
+ }
+ }
return NULL;
}
-static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels,
- ColormanageProcessor *cm_processor, bool predivide)
+static void processor_transform_apply_threaded(unsigned char *byte_buffer, float *float_buffer,
+ const int width, const int height, const int channels,
+ ColormanageProcessor *cm_processor,
+ const bool predivide, const bool float_from_byte)
{
ProcessorTransformInitData init_data;
init_data.cm_processor = cm_processor;
- init_data.buffer = buffer;
+ init_data.byte_buffer = byte_buffer;
+ init_data.float_buffer = float_buffer;
init_data.width = width;
init_data.height = height;
init_data.channels = channels;
init_data.predivide = predivide;
+ init_data.float_from_byte = float_from_byte;
IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data,
processor_transform_init_handle, do_processor_transform_thread);
@@ -1631,8 +1671,10 @@ static void processor_transform_apply_threaded(float *buffer, int width, int hei
/*********************** Color space transformation functions *************************/
/* convert the whole buffer from specified by name color space to another - internal implementation */
-static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace,
- const char *to_colorspace, bool predivide, bool do_threaded)
+static void colormanagement_transform_ex(unsigned char *byte_buffer, float *float_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace,
+ bool predivide, bool do_threaded)
{
ColormanageProcessor *cm_processor;
@@ -1649,10 +1691,19 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i
cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
- if (do_threaded)
- processor_transform_apply_threaded(buffer, width, height, channels, cm_processor, predivide);
- else
- IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide);
+ if (do_threaded) {
+ processor_transform_apply_threaded(byte_buffer, float_buffer,
+ width, height, channels,
+ cm_processor, predivide, false);
+ }
+ else {
+ if (byte_buffer != NULL) {
+ IMB_colormanagement_processor_apply_byte(cm_processor, byte_buffer, width, height, channels);
+ }
+ if (float_buffer != NULL) {
+ IMB_colormanagement_processor_apply(cm_processor, float_buffer, width, height, channels, predivide);
+ }
+ }
IMB_colormanagement_processor_free(cm_processor);
}
@@ -1661,7 +1712,7 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
const char *from_colorspace, const char *to_colorspace, bool predivide)
{
- colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false);
+ colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false);
}
/* convert the whole buffer from specified by name color space to another
@@ -1670,7 +1721,54 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha
void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
const char *from_colorspace, const char *to_colorspace, bool predivide)
{
- colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true);
+ colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true);
+}
+
+/* Similar to functions above, but operates on byte buffer. */
+void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, false);
+}
+void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, true);
+}
+
+/* Similar to above, but gets float buffer from display one. */
+void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ IMB_buffer_float_from_byte(float_buffer, byte_buffer,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ true,
+ width, height, width, width);
+ IMB_colormanagement_transform(float_buffer,
+ width, height, channels,
+ from_colorspace, to_colorspace,
+ true);
+}
+void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ ColormanageProcessor *cm_processor;
+ if (from_colorspace == NULL || from_colorspace[0] == '\0') {
+ return;
+ }
+ if (STREQ(from_colorspace, to_colorspace)) {
+ /* If source and destination color spaces are identical, skip
+ * threading overhead and simply do nothing
+ */
+ return;
+ }
+ cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
+ processor_transform_apply_threaded(byte_buffer, float_buffer,
+ width, height, channels,
+ cm_processor, true, true);
+ IMB_colormanagement_processor_free(cm_processor);
}
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace)
@@ -1974,12 +2072,14 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char
size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float);
float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space");
+ /* TODO(sergey): Convert float directly to byte buffer. */
+
memcpy(display_buffer_float, buffer, float_buffer_size);
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
- processor_transform_apply_threaded(display_buffer_float, width, height, channels,
- cm_processor, true);
+ processor_transform_apply_threaded(NULL, display_buffer_float, width, height, channels,
+ cm_processor, true, false);
IMB_buffer_byte_from_float(display_buffer, display_buffer_float,
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
@@ -3100,6 +3200,25 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
}
}
+void IMB_colormanagement_processor_apply_byte(ColormanageProcessor *cm_processor,
+ unsigned char *buffer,
+ int width, int height, int channels)
+{
+ /* TODO(sergey): Would be nice to support arbitrary channels configurations,
+ * but for now it's not so important.
+ */
+ BLI_assert(channels == 4);
+ float pixel[4];
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ size_t offset = channels * (((size_t)y) * width + x);
+ rgba_uchar_to_float(pixel, buffer + offset);
+ IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+ rgba_float_to_uchar(buffer + offset, pixel);
+ }
+ }
+}
+
void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
{
if (cm_processor->curve_mapping)
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
new file mode 100644
index 00000000000..bd456b526c7
--- /dev/null
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -0,0 +1,160 @@
+/*
+ * ***** 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): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file DNA_layer_types.h
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_LAYER_TYPES_H__
+#define __DNA_LAYER_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_listBase.h"
+
+typedef struct Base {
+ struct Base *next, *prev;
+ short flag;
+ short refcount;
+ short sx, sy;
+ struct Object *object;
+ unsigned int selcol;
+ unsigned int lay;
+ int flag_legacy;
+ int pad;
+} Base;
+
+typedef struct CollectionOverride {
+ struct CollectionOverride *next, *prev;
+ char name[64]; /* MAX_NAME */
+ /* TODO proper data */
+} CollectionOverride;
+
+typedef struct LayerCollection {
+ struct LayerCollection *next, *prev;
+ struct SceneCollection *scene_collection;
+ short flag;
+ short pad[3];
+ ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */
+ ListBase overrides;
+ ListBase layer_collections; /* synced with collection->collections */
+ ListBase engine_settings; /* CollectionEngineSettings */
+} LayerCollection;
+
+typedef struct SceneLayer {
+ struct SceneLayer *next, *prev;
+ char name[64]; /* MAX_NAME */
+ char engine[32]; /* render engine */
+ short active_collection;
+ short flag;
+ short pad[2];
+ ListBase object_bases; /* ObjectBase */
+ struct Base *basact;
+ ListBase layer_collections; /* LayerCollection */
+} SceneLayer;
+
+typedef struct SceneCollection {
+ struct SceneCollection *next, *prev;
+ char name[64]; /* MAX_NAME */
+ char filter[64]; /* MAX_NAME */
+ int active_object_index; /* for UI */
+ int pad;
+ ListBase objects; /* (Object *)LinkData->data */
+ ListBase filter_objects; /* (Object *)LinkData->data */
+ ListBase scene_collections; /* nested collections */
+} SceneCollection;
+
+/* Base->flag */
+enum {
+ BASE_SELECTED = (1 << 0),
+ BASE_VISIBLED = (1 << 1),
+ BASE_SELECTABLED = (1 << 2),
+ BASE_FROMDUPLI = (1 << 3),
+ BASE_DIRTY_ENGINE_SETTINGS = (1 << 4),
+};
+
+/* LayerCollection->flag */
+enum {
+ COLLECTION_VISIBLE = (1 << 0),
+ COLLECTION_SELECTABLE = (1 << 1),
+ COLLECTION_FOLDED = (1 << 2),
+};
+
+/* SceneLayer->flag */
+enum {
+ SCENE_LAYER_RENDER = (1 << 0),
+ SCENE_LAYER_ENGINE_DIRTY = (1 << 1),
+};
+
+
+/* *************************************************************** */
+/* Engine Settings */
+
+typedef struct CollectionEngineProperty {
+ struct CollectionEngineProperty *next, *prev;
+ char name[64]; /* MAX_NAME */
+ short type;
+ short pad;
+ char flag;
+ char pad2[3];
+} CollectionEngineProperty;
+
+typedef struct CollectionEnginePropertyInt {
+ struct CollectionEngineProperty data;
+ int value;
+ int pad;
+} CollectionEnginePropertyInt;
+
+typedef struct CollectionEnginePropertyFloat {
+ struct CollectionEngineProperty data;
+ float value;
+ float pad;
+} CollectionEnginePropertyFloat;
+
+typedef struct CollectionEngineSettings {
+ struct CollectionEngineSettings *next, *prev;
+ char name[32]; /* engine name - MAX_NAME */
+ ListBase properties; /* CollectionProperty */
+} CollectionEngineSettings;
+
+/* CollectionEngineProperty->flag */
+enum {
+ COLLECTION_PROP_USE = (1 << 0),
+};
+
+/* CollectionEntineProperty.type */
+typedef enum CollectionEnginePropertyType {
+ COLLECTION_PROP_TYPE_FLOAT = 0,
+ COLLECTION_PROP_TYPE_INT = 1,
+} CollectionEnginePropertyType;
+
+/* *************************************************************** */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DNA_LAYER_TYPES_H__ */
+
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 0c500e366a7..bd8278f897a 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -90,6 +90,43 @@ typedef struct TexPaintSlot {
int pad;
} TexPaintSlot;
+/* Material Engine Settings */
+typedef struct MaterialEngineSettings {
+ struct MaterialEngineSettings *next, *prev;
+ char name[32]; /* engine name - MAX_NAME */
+ void *data;
+} MaterialEngineSettings;
+
+/* Clay engine */
+
+/* MaterialRuntimeClay.flag */
+#define CLAY_OUTDATED 1
+
+typedef struct MaterialEngineSettingsClay {
+ short type;
+ short matcap_icon; /* Icon ID */
+
+ float matcap_rot;
+ float matcap_hue;
+ float matcap_sat;
+ float matcap_val;
+
+ float ssao_distance;
+ float ssao_attenuation;
+ float ssao_factor_cavity;
+ float ssao_factor_edge;
+
+ /* Runtime */
+ short flag;
+ short pad;
+ int ubo_index;
+} MaterialEngineSettingsClay;
+
+/* MaterialEngineSettingsClay.type */
+#define CLAY_MATCAP_NONE 0
+#define CLAY_MATCAP_SIMPLE 1
+#define CLAY_MATCAP_COMPLETE 2
+
typedef struct Material {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -203,6 +240,9 @@ typedef struct Material {
struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
* with refresh_texpaint_image_cache */
+ /* Engine Settings */
+ ListBase engines_settings; /* MaterialEngineSettings */
+
ListBase gpumaterial; /* runtime */
} Material;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index d24c7faa9f5..b92d2cd1573 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -46,6 +46,7 @@ struct Object;
struct AnimData;
struct Ipo;
struct BoundBox;
+struct CollectionEngineSettings;
struct Path;
struct Material;
struct PartDeflect;
@@ -223,7 +224,10 @@ typedef struct Object {
float jump_speed;
float fall_speed;
unsigned char max_jumps;
- char pad2[3];
+ char pad2;
+
+ /* Depsgraph */
+ short base_flag; /* used by depsgraph, flushed from base */
/** Collision mask settings */
unsigned short col_group, col_mask;
@@ -299,6 +303,8 @@ typedef struct Object {
LodLevel *currentlod;
struct PreviewImage *preview;
+
+ struct CollectionEngineSettings *collection_settings; /* used by depsgraph, flushed from collection-tree */
} Object;
/* Warning, this is not used anymore because hooks are now modifiers */
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 8310856510c..8c9de0665c4 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -99,6 +99,7 @@ enum {
#define TSE_KEYMAP_ITEM 35 /* NO ID */
#define TSE_ID_BASE 36 /* NO ID */
#define TSE_GP_LAYER 37 /* NO ID */
+#define TSE_COLLECTION 38 /* NO ID */
/* Check whether given TreeStoreElem should have a real ID in its ->id member. */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 5c7d5ed7397..8eb1d3f5da8 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -47,6 +47,8 @@ extern "C" {
#include "DNA_ID.h"
#include "DNA_freestyle_types.h"
#include "DNA_gpu_types.h"
+#include "DNA_layer_types.h"
+#include "DNA_material_types.h"
#include "DNA_userdef_types.h"
struct CurveMapping;
@@ -65,18 +67,13 @@ struct bGPdata;
struct bGPDbrush;
struct MovieClip;
struct ColorSpace;
+struct SceneCollection;
/* ************************************************************* */
/* Scene Data */
/* Base - Wrapper for referencing Objects in a Scene */
-typedef struct Base {
- struct Base *next, *prev;
- unsigned int lay, selcol;
- int flag;
- short sx, sy;
- struct Object *object;
-} Base;
+#define BaseLegacy Base
/* ************************************************************* */
/* Output Format Data */
@@ -543,6 +540,50 @@ typedef enum BakePassFilter {
#define R_BAKE_PASS_FILTER_ALL (~0)
/* *************************************************************** */
+/* Engine Settings */
+
+typedef struct RenderEngineSettings {
+ struct RenderEngineSettings *next, *prev;
+ char name[32]; /* engine name */
+ void *data;
+} RenderEngineSettings;
+
+/* Render Data */
+typedef struct RenderEngineSettingsClay {
+ /* Use same layout as MaterialEngineSettingsClay so this struct
+ * can be used as Material Settings. */
+ short type;
+ short matcap_icon; /* Icon ID */
+
+ float matcap_rot;
+ float matcap_hue;
+ float matcap_sat;
+ float matcap_val;
+
+ float ssao_distance;
+ float ssao_attenuation;
+ float ssao_factor_cavity;
+ float ssao_factor_edge;
+
+ short flag;
+ short pad;
+ int ubo_index;
+ /* end of MaterialEngineSettingsClay */
+
+ /* Global Settings */
+ short options;
+ short pad1;
+ int ssao_samples;
+ int pad2[2];
+} RenderEngineSettingsClay;
+
+/* RenderEngineSettingsClay.options */
+typedef enum ClayFlagSettings {
+ CLAY_USE_AO = (1 << 0),
+ CLAY_USE_HSV = (1 << 1),
+} ClayFlagSettings;
+
+/* *************************************************************** */
/* Render Data */
typedef struct RenderData {
@@ -1628,7 +1669,7 @@ typedef struct Scene {
struct Scene *set;
ListBase base;
- struct Base *basact; /* active base */
+ struct BaseLegacy *basact; /* active base */
struct Object *obedit; /* name replaces old G.obedit */
float cursor[3]; /* 3d cursor location */
@@ -1704,6 +1745,14 @@ typedef struct Scene {
struct RigidBodyWorld *rigidbody_world;
struct PreviewImage *preview;
+
+ ListBase render_layers;
+ struct SceneCollection *collection;
+ int active_layer;
+ int pad4;
+
+ ListBase engines_settings; /* RenderEngineSettings */
+ int pad5[2];
} Scene;
/* **************** RENDERDATA ********************* */
@@ -1892,6 +1941,7 @@ enum {
/* scene->r.engine (scene.c) */
extern const char *RE_engine_id_BLENDER_RENDER;
extern const char *RE_engine_id_BLENDER_GAME;
+extern const char *RE_engine_id_BLENDER_CLAY;
extern const char *RE_engine_id_CYCLES;
/* **************** SCENE ********************* */
@@ -1910,16 +1960,16 @@ extern const char *RE_engine_id_CYCLES;
/* depricate this! */
#define TESTBASE(v3d, base) ( \
- ((base)->flag & SELECT) && \
+ ((base)->flag_legacy & SELECT) && \
((base)->lay & v3d->lay) && \
(((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
#define TESTBASELIB(v3d, base) ( \
- ((base)->flag & SELECT) && \
+ ((base)->flag_legacy & SELECT) && \
((base)->lay & v3d->lay) && \
((base)->object->id.lib == NULL) && \
(((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
#define TESTBASELIB_BGMODE(v3d, scene, base) ( \
- ((base)->flag & SELECT) && \
+ ((base)->flag_legacy & SELECT) && \
((base)->lay & (v3d ? v3d->lay : scene->lay)) && \
((base)->object->id.lib == NULL) && \
(((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
@@ -1928,7 +1978,7 @@ extern const char *RE_engine_id_CYCLES;
((base)->object->id.lib == NULL) && \
(((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
#define BASE_SELECTABLE(v3d, base) ( \
- (base->lay & v3d->lay) && \
+ (v3d != NULL) && \
(base->object->restrictflag & (OB_RESTRICT_SELECT | OB_RESTRICT_VIEW)) == 0)
#define BASE_VISIBLE(v3d, base) ( \
(base->lay & v3d->lay) && \
@@ -1937,11 +1987,32 @@ extern const char *RE_engine_id_CYCLES;
(base->lay & (v3d ? v3d->lay : scene->lay)) && \
(base->object->restrictflag & OB_RESTRICT_VIEW) == 0)
+#define TESTBASELIB_NEW(base) ( \
+ ((base->flag & BASE_SELECTED) != 0) && \
+ ((base)->object->id.lib == NULL) && \
+ ((base->flag & BASE_VISIBLED) != 0))
+#define TESTBASELIB_BGMODE_NEW(base) ( \
+ ((base->flag & BASE_SELECTED) != 0) && \
+ (base->object->id.lib == NULL) && \
+ ((base->flag & BASE_VISIBLED) != 0))
+#define BASE_EDITABLE_BGMODE_NEW(base) ( \
+ ((base)->object->id.lib == NULL) && \
+ ((base->flag & BASE_VISIBLED) != 0))
+#define BASE_SELECTABLE_NEW(base) \
+ ((base->flag & BASE_SELECTABLED) != 0)
+#define BASE_VISIBLE_NEW(base) ( \
+ (base->flag & BASE_VISIBLED) != 0)
+
#define FIRSTBASE scene->base.first
#define LASTBASE scene->base.last
#define BASACT (scene->basact)
#define OBACT (BASACT ? BASACT->object: NULL)
+#define FIRSTBASE_NEW sl->object_bases.first
+#define LASTBASE_NEW sl->object_bases.last
+#define BASACT_NEW (sl->basact)
+#define OBACT_NEW (BASACT_NEW ? BASACT_NEW->object: NULL)
+
#define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL)
#define V3D_CAMERA_SCENE(scene, v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : (scene)->camera)
@@ -1956,7 +2027,7 @@ extern const char *RE_engine_id_CYCLES;
#define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base)
#define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base)
-/* base->flag is in DNA_object_types.h */
+/* base->legacy_flag is in DNA_object_types.h */
/* toolsettings->snap_flag */
#define SCE_SNAP 1
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 5e015544dc9..3524c041069 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -181,7 +181,8 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_CONSTRAINT = 11,
BCONTEXT_BONE_CONSTRAINT = 12,
BCONTEXT_RENDER_LAYER = 13,
-
+ BCONTEXT_COLLECTION = 14,
+
/* always as last... */
BCONTEXT_TOT
} eSpaceButtons_Context;
@@ -273,21 +274,22 @@ typedef enum eSpaceOutliner_Flag {
/* SpaceOops->outlinevis */
typedef enum eSpaceOutliner_Mode {
- SO_ALL_SCENES = 0,
- SO_CUR_SCENE = 1,
- SO_VISIBLE = 2,
- SO_SELECTED = 3,
- SO_ACTIVE = 4,
- SO_SAME_TYPE = 5,
- SO_GROUPS = 6,
- SO_LIBRARIES = 7,
- /* SO_VERSE_SESSION = 8, */ /* deprecated! */
- /* SO_VERSE_MS = 9, */ /* deprecated! */
- SO_SEQUENCE = 10,
- SO_DATABLOCKS = 11,
- SO_USERDEF = 12,
- /* SO_KEYMAP = 13, */ /* deprecated! */
- SO_ID_ORPHANS = 14,
+ SO_ALL_SCENES = 0,
+ SO_CUR_SCENE = 1,
+ SO_VISIBLE = 2,
+ SO_SELECTED = 3,
+ SO_ACTIVE = 4,
+ SO_SAME_TYPE = 5,
+ SO_GROUPS = 6,
+ SO_LIBRARIES = 7,
+ /* SO_VERSE_SESSION = 8, */ /* deprecated! */
+ /* SO_VERSE_MS = 9, */ /* deprecated! */
+ SO_SEQUENCE = 10,
+ SO_DATABLOCKS = 11,
+ SO_USERDEF = 12,
+ /* SO_KEYMAP = 13, */ /* deprecated! */
+ SO_ID_ORPHANS = 14,
+ SO_COLLECTIONS = 15,
} eSpaceOutliner_Mode;
/* SpaceOops->storeflag */
@@ -1343,6 +1345,20 @@ typedef enum eSpaceClip_GPencil_Source {
SC_GPENCIL_SRC_TRACK = 1,
} eSpaceClip_GPencil_Source;
+/* Collection Manager ======================================= */
+
+typedef struct SpaceCollections {
+ SpaceLink *next, *prev;
+ ListBase regionbase; /* storage of regions for inactive spaces */
+ int spacetype;
+ int flag; /* eSpaceCollections_Flag */
+} SpaceCollections;
+
+/* SpaceClip->flag */
+typedef enum eSpaceCollections_Flag {
+ SC_COLLECTION_DATA_REFRESH = (1 << 0), /* recreate/update SpaceCollections layer data, needed for undo/read/write */
+} eSpaceCollections_Flag;
+
/* **************** SPACE DEFINES ********************* */
/* space types, moved from DNA_screen_types.h */
@@ -1372,8 +1388,9 @@ typedef enum eSpace_Type {
SPACE_CONSOLE = 18,
SPACE_USERPREF = 19,
SPACE_CLIP = 20,
-
- SPACEICONMAX = SPACE_CLIP
+ SPACE_COLLECTIONS = 21,
+
+ SPACEICONMAX = SPACE_COLLECTIONS
} eSpace_Type;
/* use for function args */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 1dc6c7ab578..6cc24f74cee 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -390,7 +390,8 @@ typedef struct bTheme {
ThemeSpace tuserpref;
ThemeSpace tconsole;
ThemeSpace tclip;
-
+ ThemeSpace tcollections;
+
/* 20 sets of bone colors for this theme */
ThemeWireColor tarm[20];
/*ThemeWireColor tobj[20];*/
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 2cea8715a65..b6cf3d555fa 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -130,6 +130,7 @@ static const char *includefiles[] = {
"DNA_freestyle_types.h",
"DNA_linestyle_types.h",
"DNA_cachefile_types.h",
+ "DNA_layer_types.h",
/* see comment above before editing! */
/* empty string to indicate end of includefiles */
@@ -1342,4 +1343,5 @@ int main(int argc, char **argv)
#include "DNA_freestyle_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_cachefile_types.h"
+#include "DNA_layer_types.h"
/* end of list */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 66e6f30feeb..2221526fa8b 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -106,6 +106,7 @@ extern StructRNA RNA_ClothCollisionSettings;
extern StructRNA RNA_ClothModifier;
extern StructRNA RNA_ClothSettings;
extern StructRNA RNA_CloudsTexture;
+extern StructRNA RNA_CollectionEngineSettings;
extern StructRNA RNA_CollectionProperty;
extern StructRNA RNA_CollisionModifier;
extern StructRNA RNA_CollisionSensor;
@@ -317,6 +318,8 @@ extern StructRNA RNA_LaplacianSmoothModifier;
extern StructRNA RNA_Lattice;
extern StructRNA RNA_LatticeModifier;
extern StructRNA RNA_LatticePoint;
+extern StructRNA RNA_LayerCollection;
+extern StructRNA RNA_LayerCollectionOverride;
extern StructRNA RNA_Library;
extern StructRNA RNA_LimitDistanceConstraint;
extern StructRNA RNA_LimitLocationConstraint;
@@ -383,6 +386,8 @@ extern StructRNA RNA_MaterialStrand;
extern StructRNA RNA_MaterialSubsurfaceScattering;
extern StructRNA RNA_MaterialTextureSlot;
extern StructRNA RNA_MaterialVolume;
+extern StructRNA RNA_MaterialEngineSettings;
+extern StructRNA RNA_MaterialEngineSettingsClay;
extern StructRNA RNA_Mask;
extern StructRNA RNA_MaskLayer;
extern StructRNA RNA_Menu;
@@ -498,12 +503,15 @@ extern StructRNA RNA_RenderLayer;
extern StructRNA RNA_RenderPass;
extern StructRNA RNA_RenderResult;
extern StructRNA RNA_RenderSettings;
+extern StructRNA RNA_RenderEngineSettings;
+extern StructRNA RNA_RenderEngineSettingsClay;
extern StructRNA RNA_RigidBodyWorld;
extern StructRNA RNA_RigidBodyObject;
extern StructRNA RNA_RigidBodyJointConstraint;
extern StructRNA RNA_SPHFluidSettings;
extern StructRNA RNA_Scene;
extern StructRNA RNA_SceneGameData;
+extern StructRNA RNA_SceneLayer;
extern StructRNA RNA_SceneRenderLayer;
extern StructRNA RNA_SceneSequence;
extern StructRNA RNA_SceneObjects;
@@ -573,6 +581,7 @@ extern StructRNA RNA_SpaceFileBrowser;
extern StructRNA RNA_SpaceGraphEditor;
extern StructRNA RNA_SpaceImageEditor;
extern StructRNA RNA_SpaceInfo;
+extern StructRNA RNA_SpaceCollectionManager;
extern StructRNA RNA_SpaceLogicEditor;
extern StructRNA RNA_SpaceNLA;
extern StructRNA RNA_SpaceNodeEditor;
@@ -641,6 +650,7 @@ extern StructRNA RNA_ThemeFontStyle;
extern StructRNA RNA_ThemeGraphEditor;
extern StructRNA RNA_ThemeImageEditor;
extern StructRNA RNA_ThemeInfo;
+extern StructRNA RNA_ThemeCollectionManager;
extern StructRNA RNA_ThemeLogicEditor;
extern StructRNA RNA_ThemeNLAEditor;
extern StructRNA RNA_ThemeNodeEditor;
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 0f3ea27a7f9..0bf2bbb6109 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -192,6 +192,10 @@ if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
endif()
+if(WITH_CLAY_ENGINE)
+ add_definitions(-DWITH_CLAY_ENGINE)
+endif()
+
if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
@@ -341,6 +345,7 @@ blender_include_dirs(
../../bmesh
../../blentranslation
../../depsgraph
+ ../../draw
../../gpu
../../imbuf
../../ikplugin
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index d7a679e9702..27e88f592ab 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -107,6 +107,26 @@ static PointerRNA rna_Context_scene_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Scene, CTX_data_scene(C));
}
+static PointerRNA rna_Context_scene_layer_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_SceneLayer, CTX_data_scene_layer(C));
+}
+
+static PointerRNA rna_Context_scene_collection_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ ptr->id.data = CTX_data_scene(C);
+ return rna_pointer_inherit_refine(ptr, &RNA_SceneCollection, CTX_data_scene_collection(C));
+}
+
+static PointerRNA rna_Context_layer_collection_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ ptr->id.data = CTX_data_scene(C);
+ return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, CTX_data_layer_collection(C));
+}
+
static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
@@ -203,6 +223,21 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_pointer_funcs(prop, "rna_Context_scene_get", NULL, NULL, NULL);
+ prop = RNA_def_property(srna, "render_layer", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "SceneLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_scene_layer_get", NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "scene_collection", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "SceneCollection");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_scene_collection_get", NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "layer_collection", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "LayerCollection");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_layer_collection_get", NULL, NULL, NULL);
+
prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "ToolSettings");
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index aa02a3c159d..2a5a0011279 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -53,9 +53,9 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter)
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((GroupObject *)internal->link)->ob);
}
-static void rna_Group_objects_link(Group *group, bContext *C, ReportList *reports, Object *object)
+static void rna_Group_objects_link(Group *group, ReportList *reports, Object *object)
{
- if (!BKE_group_object_add(group, object, CTX_data_scene(C), NULL)) {
+ if (!BKE_group_object_add(group, object)) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' already in group '%s'", object->id.name + 2, group->id.name + 2);
return;
}
@@ -63,9 +63,9 @@ static void rna_Group_objects_link(Group *group, bContext *C, ReportList *report
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id);
}
-static void rna_Group_objects_unlink(Group *group, bContext *C, ReportList *reports, Object *object)
+static void rna_Group_objects_unlink(Group *group, ReportList *reports, Object *object)
{
- if (!BKE_group_object_unlink(group, object, CTX_data_scene(C), NULL)) {
+ if (!BKE_group_object_unlink(group, object)) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' not in group '%s'", object->id.name + 2, group->id.name + 2);
return;
}
@@ -91,7 +91,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop)
/* add object */
func = RNA_def_function(srna, "link", "rna_Group_objects_link");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Add this object to a group");
/* object to add */
parm = RNA_def_pointer(func, "object", "Object", "", "Object to add");
@@ -100,7 +100,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop)
/* remove object */
func = RNA_def_function(srna, "unlink", "rna_Group_objects_unlink");
RNA_def_function_ui_description(func, "Remove this object to a group");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
/* object to remove */
parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 76455adbc78..b904b65a37a 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -279,7 +279,7 @@ void RNA_api_material(StructRNA *srna);
void RNA_api_mesh(struct StructRNA *srna);
void RNA_api_meta(struct StructRNA *srna);
void RNA_api_object(struct StructRNA *srna);
-void RNA_api_object_base(struct StructRNA *srna);
+void RNA_api_object_base_legacy(struct StructRNA *srna);
void RNA_api_pose(struct StructRNA *srna);
void RNA_api_pose_channel(struct StructRNA *srna);
void RNA_api_scene(struct StructRNA *srna);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index b293f20dd95..4d3e3ffca26 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -313,6 +313,31 @@ static void rna_MaterialTextureSlot_use_set(PointerRNA *ptr, int value)
}
}
+static StructRNA *rna_MaterialEngineSettings_refine(PointerRNA *ptr)
+{
+#ifdef WITH_CLAY_ENGINE
+ MaterialEngineSettings *mes = (MaterialEngineSettings *)ptr->data;
+ if (STREQ(mes->name, RE_engine_id_BLENDER_CLAY)) {
+ return &RNA_MaterialEngineSettingsClay;
+ }
+#endif
+ return &RNA_MaterialEngineSettings;
+}
+
+static void rna_Material_update_engine_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+#if 0
+ Material *ma = (Material *)ptr->data;
+ RenderEngineSettings *ed = DRW_material_settings_get(ma, sce->r.engine, NULL);
+
+ if (ed->runtime) {
+ MEM_freeN(ed->runtime);
+ ed->runtime = NULL;
+ }
+#endif
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
static void rna_Material_use_diffuse_ramp_set(PointerRNA *ptr, int value)
{
Material *ma = (Material *)ptr->data;
@@ -824,6 +849,118 @@ static void rna_def_material_mtex(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Material_update");
}
+static void rna_def_material_settings_clay(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem clay_matcap_items[] = {
+ {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
+ {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
+ {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
+ {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
+ {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
+ {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
+ {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
+ {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
+ {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
+ {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
+ {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
+ {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
+ {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
+ {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
+ {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
+ {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
+ {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
+ {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
+ {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
+ {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
+ {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
+ {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
+ {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
+ {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem clay_matcap_type[] = {
+ {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
+ {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
+ {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "MaterialEngineSettingsClay", "MaterialEngineSettings");
+ RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
+ RNA_def_struct_sdna_from(srna, "MaterialEngineSettingsClay", "data");
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, clay_matcap_type);
+ RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, clay_matcap_items);
+ RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "matcap_val");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
+ RNA_def_property_range(prop, 0.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+ prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+ RNA_def_property_range(prop, 1.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+ RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+}
+
+static void rna_def_material_engine_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "MaterialEngineSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Engine Settings", "Engine specific settings");
+ RNA_def_struct_sdna(srna, "MaterialEngineSettings");
+ RNA_def_struct_refine_func(srna, "rna_MaterialEngineSettings_refine");
+
+ rna_def_material_settings_clay(brna);
+}
+
static void rna_def_material_gamesettings(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2087,6 +2224,11 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "MaterialGameSettings");
RNA_def_property_ui_text(prop, "Game Settings", "Game material settings");
+ /* Engine settings */
+ prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MaterialEngineSettings");
+ RNA_def_property_ui_text(prop, "Material Engine Settings", "Engine specific settings");
+
/* nodetree */
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
@@ -2136,6 +2278,7 @@ void RNA_def_material(BlenderRNA *brna)
rna_def_material_strand(brna);
rna_def_material_physics(brna);
rna_def_material_gamesettings(brna);
+ rna_def_material_engine_settings(brna);
RNA_api_material(srna);
}
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 0cffba47f16..f8b3bdd62e9 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -297,23 +297,14 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin
}
/* when changing the selection flag the scene needs updating */
-static void rna_Object_select_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
-{
- if (scene) {
- Object *ob = (Object *)ptr->id.data;
- short mode = (ob->flag & SELECT) ? BA_SELECT : BA_DESELECT;
- ED_base_object_select(BKE_scene_base_find(scene, ob), mode);
- }
-}
-
static void rna_Base_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Base *base = (Base *)ptr->data;
- short mode = (base->flag & BA_SELECT) ? BA_SELECT : BA_DESELECT;
+ BaseLegacy *base = (BaseLegacy *)ptr->data;
+ short mode = (base->flag_legacy & BA_SELECT) ? BA_SELECT : BA_DESELECT;
ED_base_object_select(base, mode);
}
-static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *base, Object *ob)
+static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, BaseLegacy *base, Object *ob)
{
/* try to avoid scene sort */
if (scene == NULL) {
@@ -335,7 +326,7 @@ static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *b
static void rna_Object_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
- Base *base;
+ BaseLegacy *base;
base = scene ? BKE_scene_base_find(scene, ob) : NULL;
if (!base)
@@ -351,7 +342,7 @@ static void rna_Object_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Base_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Base *base = (Base *)ptr->data;
+ BaseLegacy *base = (BaseLegacy *)ptr->data;
Object *ob = (Object *)base->object;
rna_Object_layer_update__internal(bmain, scene, base, ob);
@@ -1120,7 +1111,7 @@ static void rna_Object_layer_set(PointerRNA *ptr, const int *values)
static void rna_Base_layer_set(PointerRNA *ptr, const int *values)
{
- Base *base = (Base *)ptr->data;
+ BaseLegacy *base = (BaseLegacy *)ptr->data;
unsigned int lay;
lay = rna_Object_layer_validate__internal(values, base->lay);
@@ -2246,11 +2237,6 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Local View Layers", "3D local view layers the object is on");
- prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
- RNA_def_property_ui_text(prop, "Select", "Object selection state");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_select_update");
-
/* for data access */
prop = RNA_def_property(srna, "bound_box", PROP_FLOAT, PROP_NONE);
RNA_def_property_multi_array(prop, 2, boundbox_dimsize);
@@ -2895,14 +2881,14 @@ static void rna_def_dupli_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object");
}
-static void rna_def_object_base(BlenderRNA *brna)
+static void rna_def_object_base_legacy(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "ObjectBase", NULL);
+ srna = RNA_def_struct(brna, "ObjectBaseLegacy", NULL);
RNA_def_struct_sdna(srna, "Base");
- RNA_def_struct_ui_text(srna, "Object Base", "An object instance in a scene");
+ RNA_def_struct_ui_text(srna, "Object Base Legacy", "An object instance in a scene (deprecated)");
RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA);
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
@@ -2922,13 +2908,13 @@ static void rna_def_object_base(BlenderRNA *brna)
RNA_def_property_array(prop, 8);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Local View Layers", "3D local view layers the object base is on");
-
+
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BA_SELECT);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag_legacy", BA_SELECT);
RNA_def_property_ui_text(prop, "Select", "Object base selection state");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Base_select_update");
-
- RNA_api_object_base(srna);
+
+ RNA_api_object_base_legacy(srna);
}
void RNA_def_object(BlenderRNA *brna)
@@ -2937,7 +2923,7 @@ void RNA_def_object(BlenderRNA *brna)
RNA_define_animate_sdna(false);
rna_def_object_game_settings(brna);
- rna_def_object_base(brna);
+ rna_def_object_base_legacy(brna);
rna_def_vertex_group(brna);
rna_def_material_slot(brna);
rna_def_dupli_object(brna);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index c680abe71a4..c93f72e798f 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -40,10 +40,12 @@
#include "RNA_define.h"
#include "DNA_constraint_types.h"
+#include "DNA_layer_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "rna_internal.h" /* own include */
@@ -90,6 +92,49 @@ static EnumPropertyItem space_items[] = {
#include "DEG_depsgraph.h"
+static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports, int action)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, sl->name);
+ return;
+ }
+
+ if (action == 2) { /* TOGGLE */
+ if ((base->flag & BASE_SELECTED) != 0) {
+ action = 1; /* DESELECT */
+ }
+ else {
+ action = 0; /* SELECT */
+ }
+ }
+
+ switch (action) {
+ case 1: /* DESELECT */
+ base->flag &= ~BASE_SELECTED;
+ break;
+ case 0: /* SELECT */
+ default:
+ BKE_scene_layer_base_select(sl, base);
+ break;
+ }
+}
+
+static int rna_Object_select_get(Object *ob, bContext *C, ReportList *reports)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, sl->name);
+ return -1;
+ }
+
+ return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0;
+}
+
/* Convert a given matrix from a space to another (using the object and/or a bone as reference). */
static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan,
float *mat, float *mat_ret, int from, int to)
@@ -413,9 +458,9 @@ finally:
free_bvhtree_from_mesh(&treeData);
}
-/* ObjectBase */
+/* ObjectBaseLegacy */
-static void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d)
+static void rna_ObjectBaseLegacy_layers_from_view(BaseLegacy *base, View3D *v3d)
{
base->lay = base->object->lay = v3d->lay;
}
@@ -504,6 +549,26 @@ void RNA_api_object(StructRNA *srna)
};
#endif
+ static EnumPropertyItem object_select_items[] = {
+ {0, "SELECT", 0, "Select", "Select object from the active render layer"},
+ {1, "DESELECT", 0, "Deselect", "Deselect object from the active render layer"},
+ {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active render layer"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* Special wrapper to access the base selection value */
+ func = RNA_def_function(srna, "select_set", "rna_Object_select_set");
+ RNA_def_function_ui_description(func, "Select the object (for the active render layer)");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_enum(func, "action", object_select_items, 0, "Action", "Select mode");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "select_get", "rna_Object_select_get");
+ RNA_def_function_ui_description(func, "Get the object selection for the active render layer");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_boolean(func, "result", 0, "", "Object selected");
+ RNA_def_function_return(func, parm);
+
/* Matrix space conversion */
func = RNA_def_function(srna, "convert_space", "rna_Scene_mat_convert_space");
RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another");
@@ -707,12 +772,12 @@ void RNA_api_object(StructRNA *srna)
}
-void RNA_api_object_base(StructRNA *srna)
+void RNA_api_object_base_legacy(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *parm;
- func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBase_layers_from_view");
+ func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBaseLegacy_layers_from_view");
RNA_def_function_ui_description(func,
"Sets the object layers from a 3D View (use when adding an object in local view)");
parm = RNA_def_pointer(func, "view", "SpaceView3D", "", "");
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 1d89f7535c4..5fd4762e5be 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -605,7 +605,7 @@ static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
if (id && GS(id->name) == ID_SCE) {
Scene *scene = (Scene *)id;
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 518c7efd915..5f796261c73 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -261,6 +261,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
RNA_parameter_list_free(&list);
}
+static void engine_collection_settings_create(RenderEngine *engine, struct CollectionEngineSettings *ces)
+{
+ extern FunctionRNA rna_RenderEngine_collection_settings_create_func;
+ PointerRNA ptr,cesptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
+ RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &cesptr);
+ func = &rna_RenderEngine_collection_settings_create_func;
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "collection_settings", &cesptr);
+ engine->type->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
/* RenderEngine registration */
static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
@@ -281,7 +299,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
RenderEngineType *et, dummyet = {NULL};
RenderEngine dummyengine = {NULL};
PointerRNA dummyptr;
- int have_function[6];
+ int have_function[7];
/* setup dummy engine & engine type to store static properties in */
dummyengine.type = &dummyet;
@@ -323,8 +341,9 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
et->view_update = (have_function[3]) ? engine_view_update : NULL;
et->view_draw = (have_function[4]) ? engine_view_draw : NULL;
et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
+ et->collection_settings_create = (have_function[6]) ? engine_collection_settings_create : NULL;
- BLI_addtail(&R_engines, et);
+ RE_engines_register(bmain, et);
return et->ext.srna;
}
@@ -489,6 +508,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
parm = RNA_def_pointer(func, "node", "Node", "", "");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ /* per-collection engine settings initialization */
+ func = RNA_def_function(srna, "collection_settings_create", NULL);
+ RNA_def_function_ui_description(func, "Create the per collection settings for the engine");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "collection_settings", "CollectionEngineSettings", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+
/* tag for redraw */
func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw");
RNA_def_function_ui_description(func, "Request redraw for viewport rendering");
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 1166fb89a0a..2fb1fa9c8d6 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -32,6 +32,7 @@
#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "DNA_layer_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_userdef_types.h"
#include "DNA_world_types.h"
@@ -47,8 +48,12 @@
#include "BKE_editmesh.h"
#include "BKE_paint.h"
+#include "ED_object.h"
+
#include "GPU_extensions.h"
+#include "DRW_engine.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -77,6 +82,8 @@
#include "BLI_threads.h"
+#define NO_ENGINE "NO_ENGINE"
+
#ifdef WITH_OPENEXR
EnumPropertyItem rna_enum_exr_codec_items[] = {
{R_IMF_EXR_CODEC_NONE, "NONE", 0, "None", ""},
@@ -445,10 +452,12 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
#include "MEM_guardedalloc.h"
#include "BKE_brush.h"
+#include "BKE_collection.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
@@ -606,11 +615,11 @@ static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, Poi
static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
{
Scene *scene = (Scene *)ptr->data;
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
if (STREQLEN(base->object->id.name + 2, key, sizeof(base->object->id.name) - 2)) {
- *r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBase, base);
+ *r_ptr = rna_pointer_inherit_refine(ptr, &RNA_ObjectBaseLegacy, base);
return true;
}
}
@@ -623,13 +632,13 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter)
ListBaseIterator *internal = &iter->internal.listbase;
/* we are actually iterating a Base list, so override get */
- return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((Base *)internal->link)->object);
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((BaseLegacy *)internal->link)->object);
}
-static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob)
+static BaseLegacy *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob)
{
Scene *scene_act = CTX_data_scene(C);
- Base *base;
+ BaseLegacy *base;
if (BKE_scene_base_find(scene, ob)) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in scene '%s'", ob->id.name + 2, scene->id.name + 2);
@@ -660,7 +669,7 @@ static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *report
static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *ob)
{
- Base *base = BKE_scene_base_find(scene, ob);
+ BaseLegacy *base = BKE_scene_base_find(scene, ob);
if (!base) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in this scene '%s'", ob->id.name + 2, scene->id.name + 2);
return;
@@ -1707,7 +1716,7 @@ static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next)
BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
@@ -1778,7 +1787,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi
{
Scene *sce = ptr->id.data;
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
for (SETLOOPER(sce, sce_iter, base))
@@ -1867,6 +1876,43 @@ static void rna_GameSettings_exit_key_set(PointerRNA *ptr, int value)
gm->exitkey = value;
}
+static StructRNA *rna_RenderEngineSettings_refine(PointerRNA *ptr)
+{
+#ifdef WITH_CLAY_ENGINE
+ RenderEngineSettings *res = (RenderEngineSettings *)ptr->data;
+
+ if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
+ return &RNA_RenderEngineSettingsClay;
+ }
+#endif
+ return &RNA_RenderEngineSettings;
+}
+
+static PointerRNA rna_RenderEngineSettings_active_get(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->data;
+ RenderEngineSettings *res;
+
+ /* Ensure settings exists */
+ DRW_render_settings_get(scene, scene->r.engine);
+
+ res = BLI_findstring(&scene->engines_settings, scene->r.engine, offsetof(RenderEngineSettings, name));
+
+ return rna_pointer_inherit_refine(ptr, &RNA_RenderEngineSettings, res);
+}
+
+static void rna_RenderEngineSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Scene *sce = (Scene *)ptr->id.data;
+ MaterialEngineSettingsClay *res;
+
+ res = (MaterialEngineSettingsClay *)DRW_render_settings_get(sce, sce->r.engine);
+
+ res->flag = CLAY_OUTDATED;
+
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
static TimeMarker *rna_TimeLine_add(Scene *scene, const char name[], int frame)
{
TimeMarker *marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
@@ -2185,6 +2231,540 @@ static int rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr))
return GPU_instanced_drawing_support() && GPU_geometry_shader_support();
}
+static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ SceneCollection *sc = (SceneCollection *)ptr->data;
+ SceneCollection *sc_master = BKE_collection_master(scene);
+
+ BLI_strncpy_utf8(sc->name, value, sizeof(sc->name));
+ BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+}
+
+static void rna_SceneCollection_filter_set(PointerRNA *ptr, const char *value)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ SceneCollection *sc = (SceneCollection *)ptr->data;
+ BLI_strncpy_utf8(sc->filter, value, sizeof(sc->filter));
+
+ TODO_LAYER_SYNC_FILTER;
+ (void)scene;
+}
+
+static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *iter)
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+
+ /* we are actually iterating a LinkData list, so override get */
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((LinkData *)internal->link)->data);
+}
+
+static SceneCollection *rna_SceneCollection_new(ID *id, SceneCollection *sc_parent, const char *name)
+{
+ Scene *scene = (Scene *)id;
+ SceneCollection *sc = BKE_collection_add(scene, sc_parent, name);
+
+ DAG_id_tag_update(&scene->id, 0);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return sc;
+}
+
+static void rna_SceneCollection_remove(
+ ID *id, SceneCollection *sc_parent, ReportList *reports, PointerRNA *sc_ptr)
+{
+ Scene *scene = (Scene *)id;
+ SceneCollection *sc = sc_ptr->data;
+
+ const int index = BLI_findindex(&sc_parent->scene_collections, sc);
+ if (index == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Collection '%s' is not a sub-collection of '%s'",
+ sc->name, sc_parent->name);
+ return;
+ }
+
+ if (!BKE_collection_remove(scene, sc)) {
+ BKE_reportf(reports, RPT_ERROR, "Collection '%s' could not be removed from collection '%s'",
+ sc->name, sc_parent->name);
+ return;
+ }
+
+ RNA_POINTER_INVALIDATE(sc_ptr);
+
+ DAG_id_tag_update(&scene->id, 0);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+}
+
+static int rna_SceneCollection_objects_active_index_get(PointerRNA *ptr)
+{
+ SceneCollection *sc = (SceneCollection *)ptr->data;
+ return sc->active_object_index;
+}
+
+static void rna_SceneCollection_objects_active_index_set(PointerRNA *ptr, int value)
+{
+ SceneCollection *sc = (SceneCollection *)ptr->data;
+ sc->active_object_index = value;
+}
+
+static void rna_SceneCollection_objects_active_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ SceneCollection *sc = (SceneCollection *)ptr->data;
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&sc->objects) - 1);
+}
+
+void rna_SceneCollection_object_link(
+ ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob)
+{
+ Scene *scene = (Scene *)id;
+
+ if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in collection '%s'", ob->id.name + 2, sc->name);
+ return;
+ }
+
+ BKE_collection_object_add(scene, sc, ob);
+
+ /* TODO(sergey): Only update relations for the current scene. */
+ DAG_relations_tag_update(bmain);
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
+}
+
+static void rna_SceneCollection_object_unlink(
+ ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob)
+{
+ Scene *scene = (Scene *)id;
+
+ if (!BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in collection '%s'", ob->id.name + 2, sc->name);
+ return;
+ }
+
+ BKE_collection_object_remove(bmain, scene, sc, ob, false);
+
+ /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
+ DAG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
+}
+
+/****** layer collection engine settings *******/
+
+static StructRNA *rna_CollectionEngineSettings_refine(struct PointerRNA *ptr)
+{
+ CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;
+
+ if (STREQ(ces->name, "BLENDER_CLAY")) {
+ return &RNA_CollectionEngineSettingsClay;
+ }
+
+ /* TODO - handle other engines */
+ TODO_LAYER;
+ (void) ces;
+
+ return &RNA_CollectionEngineSettings;
+}
+
+/****** clay engine settings *******/
+
+#define RNA_LAYER_ENGINE_USE_GET_SET(_NAME_) \
+ static int rna_LayerEngineSettings_##_NAME_##_use_get(PointerRNA *ptr) \
+ { \
+ CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
+ return BKE_collection_engine_property_use_get(ces, #_NAME_) ? 1 : 0; \
+ } \
+ \
+ static void rna_LayerEngineSettings_##_NAME_##_use_set(PointerRNA *ptr, int value) \
+ { \
+ CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
+ BKE_collection_engine_property_use_set(ces, #_NAME_, value? true : false); \
+ }
+
+#define RNA_LAYER_ENGINE_GET_SET(_TYPE_, _NAME_) \
+static _TYPE_ rna_LayerEngineSettings_##_NAME_##_get(PointerRNA *ptr) \
+{ \
+ CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
+ return BKE_collection_engine_property_value_get_##_TYPE_(ces, #_NAME_); \
+} \
+ \
+static void rna_LayerEngineSettings_##_NAME_##_set(PointerRNA *ptr, _TYPE_ value) \
+{ \
+ CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
+ BKE_collection_engine_property_value_set_##_TYPE_(ces, #_NAME_, value); \
+} \
+ RNA_LAYER_ENGINE_USE_GET_SET(_NAME_)
+
+#define RNA_LAYER_ENGINE_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, _NAME_)
+
+#define RNA_LAYER_ENGINE_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, _NAME_)
+
+
+RNA_LAYER_ENGINE_GET_SET_INT(type)
+RNA_LAYER_ENGINE_GET_SET_INT(matcap_icon)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_rotation)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_hue)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_saturation)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_value)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_cavity)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_edge)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_distance)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_attenuation)
+
+#undef RNA_LAYER_ENGINE_GET_SET_INT
+#undef RNA_LAYER_ENGINE_GET_SET_FLOAT
+#undef RNA_LAYER_ENGINE_GET_SET
+#undef RNA_LAYER_ENGINE_USE_GET_SET
+
+static void rna_CollectionEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr))
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ LayerCollection *lc = CTX_data_layer_collection(C);
+ BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
+}
+
+/***********************************/
+
+static void rna_LayerCollection_name_get(PointerRNA *ptr, char *value)
+{
+ SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
+ strcpy(value, sc->name);
+}
+
+static int rna_LayerCollection_name_length(PointerRNA *ptr)
+{
+ SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
+ return strnlen(sc->name, sizeof(sc->name));
+}
+
+static void rna_LayerCollection_name_set(PointerRNA *ptr, const char *value)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
+ SceneCollection *sc_master = BKE_collection_master(scene);
+
+ BLI_strncpy_utf8(sc->name, value, sizeof(sc->name));
+ BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+}
+
+static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *iter)
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+ Base *base = ((LinkData *)internal->link)->data;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
+}
+
+static PointerRNA rna_LayerCollection_engine_settings_get(ID *UNUSED(id), LayerCollection *lc, bContext *C, const char *engine)
+{
+ Scene *scene = CTX_data_scene(C);
+ const char *engine_name;
+
+ if (STREQ(engine, NO_ENGINE)) {
+ RenderData *rd = &scene->r;
+ engine_name = rd->engine;
+ }
+ else {
+ engine_name = engine;
+ }
+
+ PointerRNA ptr;
+ CollectionEngineSettings *ces = BKE_layer_collection_engine_get(lc, engine_name);
+ RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &ptr);
+ return rna_pointer_inherit_refine(&ptr, &RNA_CollectionEngineSettings, ces);
+}
+
+static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *ptr)
+{
+ Scene *scene = CTX_data_scene(C);
+ LayerCollection *lc = ptr->data;
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc);
+
+ /* hide and deselect bases that are directly influenced by this LayerCollection */
+ BKE_scene_layer_base_flag_recalculate(sl);
+ BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+}
+
+static void rna_LayerCollection_hide_select_update(bContext *C, PointerRNA *ptr)
+{
+ LayerCollection *lc = ptr->data;
+
+ if ((lc->flag & COLLECTION_SELECTABLE) == 0) {
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc);
+
+ /* deselect bases that are directly influenced by this LayerCollection */
+ BKE_scene_layer_base_flag_recalculate(sl);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ }
+}
+
+static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ return sl->active_collection;
+}
+
+static void rna_LayerCollections_active_collection_index_set(PointerRNA *ptr, int value)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ int num_collections = BKE_layer_collection_count(sl);
+ sl->active_collection = min_ff(value, num_collections - 1);
+}
+
+static void rna_LayerCollections_active_collection_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ *min = 0;
+ *max = max_ii(0, BKE_layer_collection_count(sl) - 1);
+}
+
+static PointerRNA rna_LayerCollections_active_collection_get(PointerRNA *ptr)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ LayerCollection *lc = BKE_layer_collection_active(sl);
+ return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, lc);
+}
+
+static void rna_LayerCollections_active_collection_set(PointerRNA *ptr, PointerRNA value)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ LayerCollection *lc = (LayerCollection *)value.data;
+ const int index = BKE_layer_collection_findindex(sl, lc);
+ if (index != -1) sl->active_collection = index;
+}
+
+LayerCollection * rna_SceneLayer_collection_link(
+ ID *id, SceneLayer *sl, Main *bmain, SceneCollection *sc)
+{
+ Scene *scene = (Scene *)id;
+ LayerCollection *lc = BKE_collection_link(sl, sc);
+
+ /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */
+ DAG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, scene);
+
+ return lc;
+}
+
+static void rna_SceneLayer_collection_unlink(
+ ID *id, SceneLayer *sl, Main *bmain, ReportList *reports, LayerCollection *lc)
+{
+ Scene *scene = (Scene *)id;
+
+ if (BLI_findindex(&sl->layer_collections, lc) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' is not in '%s'", lc->scene_collection->name, sl->name);
+ return;
+ }
+
+ BKE_collection_unlink(sl, lc);
+
+ /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
+ /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */
+ DAG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
+}
+
+static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_Object, sl->basact ? sl->basact->object : NULL);
+}
+
+static void rna_LayerObjects_active_object_set(PointerRNA *ptr, PointerRNA value)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ if (value.data)
+ sl->basact = BKE_scene_layer_base_find(sl, (Object *)value.data);
+ else
+ sl->basact = NULL;
+}
+
+static void rna_SceneLayer_name_set(PointerRNA *ptr, const char *value)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ char oldname[sizeof(sl->name)];
+
+ BLI_strncpy(oldname, sl->name, sizeof(sl->name));
+
+ BLI_strncpy_utf8(sl->name, value, sizeof(sl->name));
+ BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name));
+
+ if (scene->nodetree) {
+ bNode *node;
+ int index = BLI_findindex(&scene->render_layers, sl);
+
+ for (node = scene->nodetree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS && node->id == NULL) {
+ if (node->custom1 == index)
+ BLI_strncpy(node->name, sl->name, NODE_MAXSTR);
+ }
+ }
+ }
+}
+
+static PointerRNA rna_SceneLayer_objects_get(CollectionPropertyIterator *iter)
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+
+ /* we are actually iterating a ObjectBase list, so override get */
+ Base *base = (Base *)internal->link;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
+}
+
+static int rna_SceneLayer_objects_selected_skip(CollectionPropertyIterator *iter, void *UNUSED(data))
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+ Base *base = (Base *)internal->link;
+
+ if ((base->flag & BASE_SELECTED) != 0) {
+ return 0;
+ }
+
+ return 1;
+};
+
+static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ rna_iterator_listbase_begin(iter, &sl->object_bases, rna_SceneLayer_objects_selected_skip);
+}
+
+static void rna_SceneLayer_engine_set(PointerRNA *ptr, int value)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ RenderEngineType *type = BLI_findlink(&R_engines, value);
+
+ if (type)
+ BKE_scene_layer_engine_set(sl, type->idname);
+}
+
+static EnumPropertyItem *rna_SceneLayer_engine_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ RenderEngineType *type;
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int a = 0, totitem = 0;
+
+ for (type = R_engines.first; type; type = type->next, a++) {
+ tmp.value = a;
+ tmp.identifier = type->idname;
+ tmp.name = type->name;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static int rna_SceneLayer_engine_get(PointerRNA *ptr)
+{
+ SceneLayer *sl = (SceneLayer *)ptr->data;
+ RenderEngineType *type;
+ int a = 0;
+
+ for (type = R_engines.first; type; type = type->next, a++)
+ if (STREQ(type->idname, sl->engine))
+ return a;
+
+ return 0;
+}
+
+static void rna_SceneLayer_engine_update(Main *bmain, Scene *UNUSED(unused), PointerRNA *UNUSED(ptr))
+{
+ ED_render_engine_changed(bmain);
+}
+
+static int rna_SceneLayer_multiple_engines_get(PointerRNA *UNUSED(ptr))
+{
+ return (BLI_listbase_count(&R_engines) > 1);
+}
+
+static int rna_SceneLayer_active_layer_index_get(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->data;
+ return scene->active_layer;
+}
+
+static void rna_SceneLayer_active_layer_index_set(PointerRNA *ptr, int value)
+{
+ Scene *scene = (Scene *)ptr->data;
+ int num_layers = BLI_listbase_count(&scene->render_layers);
+ scene->active_layer = min_ff(value, num_layers - 1);
+}
+
+static void rna_SceneLayer_active_layer_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ Scene *scene = (Scene *)ptr->data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&scene->render_layers) - 1);
+}
+
+static PointerRNA rna_SceneLayer_active_layer_get(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->data;
+ SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer);
+
+ return rna_pointer_inherit_refine(ptr, &RNA_SceneLayer, sl);
+}
+
+static void rna_SceneLayer_active_layer_set(PointerRNA *ptr, PointerRNA value)
+{
+ Scene *scene = (Scene *)ptr->data;
+ SceneLayer *sl = (SceneLayer *)value.data;
+ const int index = BLI_findindex(&scene->render_layers, sl);
+ if (index != -1) scene->active_layer = index;
+}
+
+static SceneLayer *rna_SceneLayer_new(ID *id, Scene *UNUSED(sce), const char *name)
+{
+ Scene *scene = (Scene *)id;
+ SceneLayer *sl = BKE_scene_layer_add(scene, name);
+
+ DAG_id_tag_update(&scene->id, 0);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return sl;
+}
+
+static void rna_SceneLayer_remove(
+ ID *id, Scene *UNUSED(sce), Main *bmain, ReportList *reports, PointerRNA *sl_ptr)
+{
+ Scene *scene = (Scene *)id;
+ SceneLayer *sl = sl_ptr->data;
+
+ if (!BKE_scene_layer_remove(bmain, scene, sl)) {
+ BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'",
+ sl->name, scene->id.name + 2);
+ return;
+ }
+
+ RNA_POINTER_INVALIDATE(sl_ptr);
+
+ DAG_id_tag_update(&scene->id, 0);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+}
+
+static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Base *base = (Base *)ptr->data;
+ short mode = (base->flag & BASE_SELECTED) ? BA_SELECT : BA_DESELECT;
+ ED_object_base_select(base, mode);
+}
+
#else
/* Grease Pencil Interpolation tool settings */
@@ -5046,6 +5626,545 @@ static void rna_def_gpu_fx(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
}
+/* Render Layers and Collections */
+
+static void rna_def_scene_collections(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "SceneCollections");
+ srna = RNA_def_struct(brna, "SceneCollections", NULL);
+ RNA_def_struct_sdna(srna, "SceneCollection");
+ RNA_def_struct_ui_text(srna, "Scene Collection", "Collection of scene collections");
+
+ func = RNA_def_function(srna, "new", "rna_SceneCollection_new");
+ RNA_def_function_ui_description(func, "Add a collection to scene");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_string(func, "name", "SceneCollection", 0, "", "New name for the collection (not unique)");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_SceneCollection_remove");
+ RNA_def_function_ui_description(func, "Remove a collection layer");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ parm = RNA_def_pointer(func, "layer", "SceneCollection", "", "Collection to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+}
+
+static void rna_def_collection_objects(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "CollectionObjects");
+ srna = RNA_def_struct(brna, "CollectionObjects", NULL);
+ RNA_def_struct_sdna(srna, "SceneCollection");
+ RNA_def_struct_ui_text(srna, "Collection Objects", "Objects of a collection");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_SceneCollection_objects_active_index_get",
+ "rna_SceneCollection_objects_active_index_set",
+ "rna_SceneCollection_objects_active_index_range");
+ RNA_def_property_ui_text(prop, "Active Object Index", "Active index in collection objects array");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
+ func = RNA_def_function(srna, "link", "rna_SceneCollection_object_link");
+ RNA_def_function_ui_description(func, "Link an object to collection");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "object", "Object", "", "Object to add to collection");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "unlink", "rna_SceneCollection_object_unlink");
+ RNA_def_function_ui_description(func, "Unlink object from collection");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove from collection");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+}
+
+static void rna_def_scene_collection(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "SceneCollection", NULL);
+ RNA_def_struct_ui_text(srna, "Scene Collection", "Collection");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Collection name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
+ prop = RNA_def_property(srna, "filter", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_filter_set");
+ RNA_def_property_ui_text(prop, "Filter", "Filter to dynamically include objects based on their names (e.g., CHAR_*)");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
+ prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "scene_collections", NULL);
+ RNA_def_property_struct_type(prop, "SceneCollection");
+ RNA_def_property_ui_text(prop, "SceneCollections", "");
+ rna_def_scene_collections(brna, prop);
+
+ prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "objects", NULL);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Objects", "All the objects directly added to this collection (not including sub-collection objects)");
+ rna_def_collection_objects(brna, prop);
+
+ prop = RNA_def_property(srna, "filters_objects", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "filter_objects", NULL);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Filter Objects", "All the objects dynamically added to this collection via the filter");
+}
+
+static void rna_def_layer_collection_override(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LayerCollectionOverride", NULL);
+ RNA_def_struct_sdna(srna, "CollectionOverride");
+ RNA_def_struct_ui_text(srna, "Collection Override", "Collection Override");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Collection name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+}
+
+#define RNA_LAYER_ENGINE_USE(_NAME_) \
+ prop = RNA_def_property(srna, #_NAME_"_use", PROP_BOOLEAN, PROP_NONE); \
+ RNA_def_property_boolean_funcs(prop, \
+ "rna_LayerEngineSettings_"#_NAME_"_use_get", \
+ "rna_LayerEngineSettings_"#_NAME_"_use_set"); \
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); \
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+
+static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem clay_matcap_items[] = {
+ {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
+ {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
+ {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
+ {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
+ {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
+ {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
+ {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
+ {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
+ {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
+ {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
+ {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
+ {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
+ {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
+ {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
+ {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
+ {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
+ {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
+ {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
+ {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
+ {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
+ {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
+ {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
+ {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
+ {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem clay_matcap_type[] = {
+ {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
+ {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
+ {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "CollectionEngineSettingsClay", NULL);
+ RNA_def_struct_sdna(srna, "CollectionEngineSettings");
+ RNA_def_struct_ui_text(srna, "Collections Clay Engine Settings", "Engine specific settings for this collection");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Engine name");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_type_get", "rna_LayerEngineSettings_type_set", NULL);
+ RNA_def_property_enum_items(prop, clay_matcap_type);
+ RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(type)
+
+ prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_matcap_icon_get", "rna_LayerEngineSettings_matcap_icon_set", NULL);
+ RNA_def_property_enum_items(prop, clay_matcap_items);
+ RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(matcap_icon)
+
+ prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_rotation_get", "rna_LayerEngineSettings_matcap_rotation_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(matcap_rotation)
+
+ prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_hue_get", "rna_LayerEngineSettings_matcap_hue_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(matcap_hue)
+
+ prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_saturation_get", "rna_LayerEngineSettings_matcap_saturation_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(matcap_saturation)
+
+ prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_value_get", "rna_LayerEngineSettings_matcap_value_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(matcap_value)
+
+ prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_cavity_get", "rna_LayerEngineSettings_ssao_factor_cavity_set", NULL);
+ RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(ssao_factor_cavity)
+
+ prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_edge_get", "rna_LayerEngineSettings_ssao_factor_edge_set", NULL);
+ RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(ssao_factor_edge)
+
+ prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_distance_get", "rna_LayerEngineSettings_ssao_distance_set", NULL);
+ RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
+ RNA_def_property_range(prop, 0.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(ssao_distance)
+
+ prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_attenuation_get", "rna_LayerEngineSettings_ssao_attenuation_set", NULL);
+ RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+ RNA_def_property_range(prop, 1.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+ RNA_LAYER_ENGINE_USE(ssao_attenuation)
+}
+
+static void rna_def_layer_collection_engine_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "CollectionEngineSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Collections Engine Settings", "Engine specific settings for this collection");
+ RNA_def_struct_refine_func(srna, "rna_CollectionEngineSettings_refine");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Engine name");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+
+ /* the engine specific structs */
+ rna_def_layer_collection_engine_settings_clay(brna);
+}
+
+#undef RNA_LAYER_ENGINE_USE
+
+static void rna_def_layer_collection(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, "LayerCollection", NULL);
+ RNA_def_struct_ui_text(srna, "Layer Collection", "Layer collection");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_LayerCollection_name_get", "rna_LayerCollection_name_length", "rna_LayerCollection_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Collection name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
+ prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "scene_collection");
+ RNA_def_property_struct_type(prop, "SceneCollection");
+ RNA_def_property_ui_text(prop, "Collection", "Collection this layer collection is wrapping");
+
+ prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "layer_collections", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollection");
+ RNA_def_property_ui_text(prop, "Layer Collections", "");
+
+ prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_LayerCollection_objects_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Objects", "All the objects directly or indirectly added to this collection (not including sub-collection objects)");
+
+ prop = RNA_def_property(srna, "overrides", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "overrides", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollectionOverride");
+ RNA_def_property_ui_text(prop, "Collection Overrides", "");
+
+ func = RNA_def_function(srna, "get_engine_settings", "rna_LayerCollection_engine_settings_get");
+ RNA_def_function_ui_description(func, "Return the engine settings for this collection");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT);
+ parm = RNA_def_string(func, "engine", NO_ENGINE, MAX_NAME, "Engine", "use context one by default");
+ RNA_def_parameter_clear_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "result", "CollectionEngineSettings", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_return(func, parm);
+
+ /* Flags */
+ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_VISIBLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
+ RNA_def_property_ui_text(prop, "Hide", "Restrict visiblity");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_update");
+
+ prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_SELECTABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1);
+ RNA_def_property_ui_text(prop, "Hide Selectable", "Restrict selection");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_select_update");
+
+ prop = RNA_def_property(srna, "is_unfolded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_FOLDED);
+ RNA_def_property_ui_icon(prop, ICON_RIGHTARROW, 1);
+ RNA_def_property_ui_text(prop, "Folded", "Folded collection");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
+ /* TODO_LAYER_OVERRIDE */
+}
+
+static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *prop;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "LayerCollections");
+ srna = RNA_def_struct(brna, "LayerCollections", NULL);
+ RNA_def_struct_sdna(srna, "SceneLayer");
+ RNA_def_struct_ui_text(srna, "Layer Collections", "Collections of render layer");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "active_collection");
+ RNA_def_property_int_funcs(prop, "rna_LayerCollections_active_collection_index_get",
+ "rna_LayerCollections_active_collection_index_set",
+ "rna_LayerCollections_active_collection_index_range");
+ RNA_def_property_ui_text(prop, "Active Collection Index", "Active index in layer collection array");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "LayerCollection");
+ RNA_def_property_pointer_funcs(prop, "rna_LayerCollections_active_collection_get",
+ "rna_LayerCollections_active_collection_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Active Layer Collection", "Active Layer Collection");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
+
+ func = RNA_def_function(srna, "link", "rna_SceneLayer_collection_link");
+ RNA_def_function_ui_description(func, "Link a collection to render layer");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "scene_collection", "SceneCollection", "", "Collection to add to render layer");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "result", "LayerCollection", "", "Newly created layer collection");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "unlink", "rna_SceneLayer_collection_unlink");
+ RNA_def_function_ui_description(func, "Unlink a collection from render layer");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "layer_collection", "LayerCollection", "", "Layer collection to remove from render layer");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+}
+
+static void rna_def_layer_objects(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "LayerObjects");
+ srna = RNA_def_struct(brna, "LayerObjects", NULL);
+ RNA_def_struct_sdna(srna, "SceneLayer");
+ RNA_def_struct_ui_text(srna, "Layer Objects", "Collections of objects");
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_pointer_funcs(prop, "rna_LayerObjects_active_object_get", "rna_LayerObjects_active_object_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Object", "Active object for this layer");
+ /* Could call: ED_base_object_activate(C, rl->basact);
+ * but would be a bad level call and it seems the notifier is enough */
+ RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
+
+ prop = RNA_def_property(srna, "selected", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_collection_funcs(prop, "rna_LayerObjects_selected_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_SceneLayer_objects_get",
+ NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Selected Objects", "All the selected objects of this layer");
+}
+
+static void rna_def_scene_layer(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem engine_items[] = {
+ {0, "BLENDER_RENDER", 0, "Blender Render", "Use the Blender internal rendering engine for rendering"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "SceneLayer", NULL);
+ RNA_def_struct_ui_text(srna, "Render Layer", "Render layer");
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneLayer_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Render layer name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+
+ prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "layer_collections", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollection");
+ RNA_def_property_ui_text(prop, "Layer Collections", "");
+ rna_def_layer_collections(brna, prop);
+
+ prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneLayer_objects_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Objects", "All the objects in this layer");
+ rna_def_layer_objects(brna, prop);
+
+ /* layer options */
+ prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SCENE_LAYER_RENDER);
+ RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
+
+ /* engine */
+ prop = RNA_def_property(srna, "engine", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, engine_items);
+ RNA_def_property_enum_funcs(prop, "rna_SceneLayer_engine_get", "rna_SceneLayer_engine_set",
+ "rna_SceneLayer_engine_itemf");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Engine", "Engine to use for rendering");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_SceneLayer_engine_update");
+
+ prop = RNA_def_property(srna, "has_multiple_engines", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_SceneLayer_multiple_engines_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Multiple Engines", "More than one rendering engine is available");
+}
+
+static void rna_def_scene_layers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "SceneLayers");
+ srna = RNA_def_struct(brna, "SceneLayers", NULL);
+ RNA_def_struct_sdna(srna, "Scene");
+ RNA_def_struct_ui_text(srna, "Render Layers", "Collection of render layers");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "active_layer");
+ RNA_def_property_int_funcs(prop, "rna_SceneLayer_active_layer_index_get",
+ "rna_SceneLayer_active_layer_index_set",
+ "rna_SceneLayer_active_layer_index_range");
+ RNA_def_property_ui_text(prop, "Active Layer Index", "Active index in render layer array");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "SceneLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_SceneLayer_active_layer_get",
+ "rna_SceneLayer_active_layer_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Active Render Layer", "Active Render Layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
+
+ func = RNA_def_function(srna, "new", "rna_SceneLayer_new");
+ RNA_def_function_ui_description(func, "Add a render layer to scene");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_string(func, "name", "SceneLayer", 0, "", "New name for the render layer (not unique)");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "result", "SceneLayer", "", "Newly created render layer");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_SceneLayer_remove");
+ RNA_def_function_ui_description(func, "Remove a render layer");
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ parm = RNA_def_pointer(func, "layer", "SceneLayer", "", "Render layer to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+}
+
+static void rna_def_object_base(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ObjectBase", NULL);
+ RNA_def_struct_sdna(srna, "Base");
+ RNA_def_struct_ui_text(srna, "Object Base", "An object instance in a render layer");
+ RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA);
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "object");
+ RNA_def_property_ui_text(prop, "Object", "Object this base links to");
+
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_SELECTED);
+ RNA_def_property_ui_text(prop, "Select", "Object base selection state");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ObjectBase_select_update");
+}
+
+/* TODO LAYERS: legacy SceneRenderLayers, to be removed */
static void rna_def_scene_render_layer(BlenderRNA *brna)
{
@@ -5774,6 +6893,115 @@ static void rna_def_scene_quicktime_settings(BlenderRNA *brna)
}
#endif
+#ifdef WITH_CLAY_ENGINE
+static void rna_def_render_engine_settings_clay(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ static EnumPropertyItem clay_matcap_items[] = {
+ {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
+ {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
+ {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
+ {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
+ {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
+ {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
+ {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
+ {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
+ {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
+ {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
+ {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
+ {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
+ {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
+ {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
+ {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
+ {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
+ {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
+ {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
+ {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
+ {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
+ {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
+ {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
+ {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
+ {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "RenderEngineSettingsClay", "RenderEngineSettings");
+ RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
+ RNA_def_struct_sdna_from(srna, "RenderEngineSettingsClay", "data");
+
+ prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, clay_matcap_items);
+ RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "matcap_val");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
+ RNA_def_property_range(prop, 0.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+ RNA_def_property_range(prop, 1.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+ RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+ /* Clay settings */
+ prop = RNA_def_property(srna, "ssao_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples");
+ RNA_def_property_range(prop, 1, 500);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+#endif
+
+static void rna_def_scene_render_engine(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "RenderEngineSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Render Engine Settings", "Engine specific render settings");
+ RNA_def_struct_sdna(srna, "RenderEngineSettings");
+ RNA_def_struct_refine_func(srna, "rna_RenderEngineSettings_refine");
+
+#ifdef WITH_CLAY_ENGINE
+ rna_def_render_engine_settings_clay(brna);
+#endif
+}
+
static void rna_def_scene_render_data(BlenderRNA *brna)
{
StructRNA *srna;
@@ -6760,7 +7988,7 @@ static void rna_def_scene_objects(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to add to scene");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "base", "ObjectBase", "", "The newly created base");
+ parm = RNA_def_pointer(func, "base", "ObjectBaseLegacy", "", "The newly created base");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "unlink", "rna_Scene_object_unlink");
@@ -6795,7 +8023,7 @@ static void rna_def_scene_bases(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "Scene Bases", "Collection of scene bases");
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "ObjectBase");
+ RNA_def_property_struct_type(prop, "ObjectBaseLegacy");
RNA_def_property_pointer_sdna(prop, NULL, "basact");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Active Base", "Active object base in the scene");
@@ -7039,7 +8267,7 @@ void RNA_def_scene(BlenderRNA *brna)
/* Bases/Objects */
prop = RNA_def_property(srna, "object_bases", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "base", NULL);
- RNA_def_property_struct_type(prop, "ObjectBase");
+ RNA_def_property_struct_type(prop, "ObjectBaseLegacy");
RNA_def_property_ui_text(prop, "Bases", "");
RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
"rna_Scene_object_bases_lookup_string", NULL);
@@ -7269,7 +8497,17 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "r");
RNA_def_property_struct_type(prop, "RenderSettings");
RNA_def_property_ui_text(prop, "Render Data", "");
-
+
+ /* Render Engine Data */
+ prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "RenderEngineSettings");
+ RNA_def_property_ui_text(prop, "Render Engine Settings", "Engine specific render settings");
+
+ prop = RNA_def_property(srna, "active_engine_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "RenderEngineSettings");
+ RNA_def_property_pointer_funcs(prop, "rna_RenderEngineSettings_active_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active Render Engine Settings", "Active Engine specific render settings for this scene");
+
/* Safe Areas */
prop = RNA_def_property(srna, "safe_areas", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "safe_areas");
@@ -7385,6 +8623,19 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Depsgraph");
RNA_def_property_ui_text(prop, "Dependency Graph", "Dependencies in the scene data");
+ /* Layer and Collections */
+ prop = RNA_def_property(srna, "render_layers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "render_layers", NULL);
+ RNA_def_property_struct_type(prop, "SceneLayer");
+ RNA_def_property_ui_text(prop, "Render Layers", "");
+ rna_def_scene_layers(brna, prop);
+
+ prop = RNA_def_property(srna, "master_collection", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "collection");
+ RNA_def_property_struct_type(prop, "SceneCollection");
+ RNA_def_property_ui_text(prop, "Master Collection", "Collection that contains all other collections");
+
/* Nestled Data */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
@@ -7400,9 +8651,16 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_transform_orientation(brna);
rna_def_selected_uv_element(brna);
rna_def_display_safe_areas(brna);
+ rna_def_scene_collection(brna);
+ rna_def_layer_collection(brna);
+ rna_def_layer_collection_override(brna);
+ rna_def_layer_collection_engine_settings(brna);
+ rna_def_scene_layer(brna);
+ rna_def_object_base(brna);
RNA_define_animate_sdna(true);
/* *** Animated *** */
rna_def_scene_render_data(brna);
+ rna_def_scene_render_engine(brna);
rna_def_scene_render_layer(brna);
rna_def_gpu_fx(brna);
rna_def_scene_render_view(brna);
@@ -7412,3 +8670,5 @@ void RNA_def_scene(BlenderRNA *brna)
}
#endif
+
+#undef NO_ENGINE
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 92e7d9a7939..aa3346ec653 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -79,6 +79,7 @@ EnumPropertyItem rna_enum_space_type_items[] = {
{0, "", ICON_NONE, NULL, NULL},
{SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"},
{SPACE_OUTLINER, "OUTLINER", ICON_OOPS, "Outliner", "Overview of scene graph and all available data-blocks"},
+ {SPACE_COLLECTIONS, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collections", "Edit collections of active render layer"},
{SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences", "Edit persistent configuration settings"},
{SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages (drag down to expand and display)"},
{0, "", ICON_NONE, NULL, NULL},
@@ -210,6 +211,7 @@ static EnumPropertyItem buttons_context_items[] = {
{BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"},
{BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"},
{BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"},
+ {BCONTEXT_COLLECTION, "COLLECTION", ICON_COLLAPSEMENU, "Collection", "Collection"},
{0, NULL, 0, NULL, NULL}
};
@@ -317,6 +319,8 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr)
return &RNA_SpaceUserPreferences;
case SPACE_CLIP:
return &RNA_SpaceClipEditor;
+ case SPACE_COLLECTIONS:
+ return &RNA_SpaceCollectionManager;
default:
return &RNA_Space;
}
@@ -1080,6 +1084,10 @@ static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSED(C),
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_SCENE);
}
+ if (sbuts->pathflag & (1 << BCONTEXT_COLLECTION)) {
+ RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_COLLECTION);
+ }
+
if (sbuts->pathflag & (1 << BCONTEXT_WORLD)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORLD);
}
@@ -2104,6 +2112,7 @@ static void rna_def_space_outliner(BlenderRNA *brna)
{SO_USERDEF, "USER_PREFERENCES", 0, "User Preferences", "Display user preference data"},
{SO_ID_ORPHANS, "ORPHAN_DATA", 0, "Orphan Data",
"Display data-blocks which are unused and/or will be lost when the file is reloaded"},
+ {SO_COLLECTIONS, "COLLECTIONS", 0, "Collections", "Display the collections of the active render layer"},
{0, NULL, 0, NULL, NULL}
};
@@ -4815,6 +4824,15 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
}
+static void rna_def_space_collections(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "SpaceCollectionManager", "Space");
+ RNA_def_struct_sdna(srna, "SpaceCollections");
+ RNA_def_struct_ui_text(srna, "Space Collection Manager", "Layer Collection space data");
+}
+
void RNA_def_space(BlenderRNA *brna)
{
@@ -4841,6 +4859,7 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_space_node(brna);
rna_def_space_logic(brna);
rna_def_space_clip(brna);
+ rna_def_space_collections(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 57db23563f5..06b8e6e0737 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2956,6 +2956,26 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
}
+static void rna_def_userdef_theme_space_collections(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ThemeCollectionManager", NULL);
+ RNA_def_struct_sdna(srna, "ThemeSpace");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Theme Collection Manager", "Theme settings for the Collection Manager");
+
+ rna_def_userdef_theme_spaces_main(srna);
+ rna_def_userdef_theme_spaces_list_main(srna);
+
+ prop = RNA_def_property(srna, "selected_collection", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "hilite");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Selected Collection", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+}
+
static void rna_def_userdef_themes(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2982,6 +3002,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
{16, "FILE_BROWSER", ICON_FILESEL, "File Browser", ""},
{17, "CONSOLE", ICON_CONSOLE, "Python Console", ""},
{20, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", ""},
+ {21, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collection Manager", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3115,6 +3136,12 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "tclip");
RNA_def_property_struct_type(prop, "ThemeClipEditor");
RNA_def_property_ui_text(prop, "Clip Editor", "");
+
+ prop = RNA_def_property(srna, "collection_manager", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "tcollections");
+ RNA_def_property_struct_type(prop, "ThemeCollectionManager");
+ RNA_def_property_ui_text(prop, "Collection Manager", "");
}
static void rna_def_userdef_addon(BlenderRNA *brna)
@@ -3205,6 +3232,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna)
rna_def_userdef_theme_space_console(brna);
rna_def_userdef_theme_space_logic(brna);
rna_def_userdef_theme_space_clip(brna);
+ rna_def_userdef_theme_space_collections(brna);
rna_def_userdef_theme_colorset(brna);
rna_def_userdef_themes(brna);
}
@@ -3937,7 +3965,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dpi");
- RNA_def_property_range(prop, 16, 256);
+ RNA_def_property_range(prop, 48, 144);
RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 8efa4d63675..8aee7b66916 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -96,7 +96,7 @@ static void foreachObjectLink(
{
ArmatureModifierData *amd = (ArmatureModifierData *) md;
- walk(userData, ob, &amd->object, IDWALK_NOP);
+ walk(userData, ob, &amd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 6017f964c26..61ac4d5692f 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -95,10 +95,10 @@ static void foreachObjectLink(
{
ArrayModifierData *amd = (ArrayModifierData *) md;
- walk(userData, ob, &amd->start_cap, IDWALK_NOP);
- walk(userData, ob, &amd->end_cap, IDWALK_NOP);
- walk(userData, ob, &amd->curve_ob, IDWALK_NOP);
- walk(userData, ob, &amd->offset_ob, IDWALK_NOP);
+ walk(userData, ob, &amd->start_cap, IDWALK_CB_NOP);
+ walk(userData, ob, &amd->end_cap, IDWALK_CB_NOP);
+ walk(userData, ob, &amd->curve_ob, IDWALK_CB_NOP);
+ walk(userData, ob, &amd->offset_ob, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index d2f19b78b50..51020566de6 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -101,7 +101,7 @@ static void foreachObjectLink(
{
BooleanModifierData *bmd = (BooleanModifierData *) md;
- walk(userData, ob, &bmd->object, IDWALK_NOP);
+ walk(userData, ob, &bmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 16c5de45c49..9e718eab639 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -102,7 +102,7 @@ static void foreachObjectLink(
{
CastModifierData *cmd = (CastModifierData *) md;
- walk(userData, ob, &cmd->object, IDWALK_NOP);
+ walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index b6a7b5b57ec..59eb00207df 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -214,11 +214,11 @@ static void foreachIDLink(ModifierData *md, Object *ob,
ClothModifierData *clmd = (ClothModifierData *) md;
if (clmd->coll_parms) {
- walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_CB_NOP);
}
if (clmd->sim_parms && clmd->sim_parms->effector_weights) {
- walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_NOP);
}
}
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 3e9b46ad8ea..6f3dbe841aa 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -89,7 +89,7 @@ static void foreachObjectLink(
{
CurveModifierData *cmd = (CurveModifierData *) md;
- walk(userData, ob, &cmd->object, IDWALK_NOP);
+ walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index 26952e1e0d5..3bddbc7ee2b 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -124,7 +124,7 @@ static void foreachObjectLink(
ObjectWalkFunc walk, void *userData)
{
DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
- walk(userData, ob, &dtmd->ob_source, IDWALK_NOP);
+ walk(userData, ob, &dtmd->ob_source, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
@@ -163,7 +163,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
/* Only used to check wehther we are operating on org data or not... */
Mesh *me = ob->data;
- MVert *mvert;
const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;
@@ -176,8 +175,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
BLI_SPACE_TRANSFORM_SETUP(space_transform, ob, dtmd->ob_source);
}
- mvert = dm->getVertArray(dm);
- if ((me->mvert == mvert) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) {
+ MVert *mvert = dm->getVertArray(dm);
+ MEdge *medge = dm->getEdgeArray(dm);
+ if (((me->mvert == mvert) || (me->medge == medge)) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) {
/* We need to duplicate data here, otherwise setting custom normals, edges' shaprness, etc., could
* modify org mesh, see T43671. */
dm = CDDM_copy(dm);
@@ -195,6 +195,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
if (BKE_reports_contain(&reports, RPT_ERROR)) {
modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR));
}
+ else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) {
+ modifier_setError((ModifierData *)dtmd, "Enable 'Auto Smooth' option in mesh settings");
+ }
else if (dm->getNumVerts(dm) > HIGH_POLY_WARNING || ((Mesh *)(dtmd->ob_source->data))->totvert > HIGH_POLY_WARNING) {
modifier_setError(md, "You are using a rather high poly as source or destination, computation might be slow");
}
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 4b5181e9c61..43e7ac238d1 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -38,10 +38,12 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
+#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_texture.h"
@@ -132,7 +134,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
{
DisplaceModifierData *dmd = (DisplaceModifierData *) md;
- walk(userData, ob, &dmd->map_object, IDWALK_NOP);
+ walk(userData, ob, &dmd->map_object, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -140,7 +142,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
DisplaceModifierData *dmd = (DisplaceModifierData *) md;
- walk(userData, ob, (ID **)&dmd->texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&dmd->texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
@@ -175,21 +177,130 @@ static void updateDepsgraph(ModifierData *md,
}
}
+typedef struct DisplaceUserdata {
+ /*const*/ DisplaceModifierData *dmd;
+ struct ImagePool *pool;
+ MDeformVert *dvert;
+ float weight;
+ int defgrp_index;
+ int direction;
+ bool use_global_direction;
+ float (*tex_co)[3];
+ float (*vertexCos)[3];
+ float local_mat[4][4];
+ MVert *mvert;
+ float (*vert_clnors)[3];
+} DisplaceUserdata;
+
+static void displaceModifier_do_task(void *userdata, const int iter)
+{
+ DisplaceUserdata *data = (DisplaceUserdata *)userdata;
+ DisplaceModifierData *dmd = data->dmd;
+ MDeformVert *dvert = data->dvert;
+ float weight = data->weight;
+ int defgrp_index = data->defgrp_index;
+ int direction = data->direction;
+ bool use_global_direction = data->use_global_direction;
+ float (*tex_co)[3] = data->tex_co;
+ float (*vertexCos)[3] = data->vertexCos;
+ MVert *mvert = data->mvert;
+ float (*vert_clnors)[3] = data->vert_clnors;
+
+ const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */
+
+ TexResult texres;
+ float strength = dmd->strength;
+ float delta;
+ float local_vec[3];
+
+ if (dvert) {
+ weight = defvert_find_weight(dvert + iter, defgrp_index);
+ if (weight == 0.0f) {
+ return;
+ }
+ }
+
+ if (dmd->texture) {
+ texres.nor = NULL;
+ BKE_texture_get_value_ex(dmd->modifier.scene, dmd->texture, tex_co[iter], &texres, data->pool, false);
+ delta = texres.tin - dmd->midlevel;
+ }
+ else {
+ delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */
+ }
+
+ if (dvert) {
+ strength *= weight;
+ }
+
+ delta *= strength;
+ CLAMP(delta, -10000, 10000);
+
+ switch (direction) {
+ case MOD_DISP_DIR_X:
+ if (use_global_direction) {
+ vertexCos[iter][0] += delta * data->local_mat[0][0];
+ vertexCos[iter][1] += delta * data->local_mat[1][0];
+ vertexCos[iter][2] += delta * data->local_mat[2][0];
+ }
+ else {
+ vertexCos[iter][0] += delta;
+ }
+ break;
+ case MOD_DISP_DIR_Y:
+ if (use_global_direction) {
+ vertexCos[iter][0] += delta * data->local_mat[0][1];
+ vertexCos[iter][1] += delta * data->local_mat[1][1];
+ vertexCos[iter][2] += delta * data->local_mat[2][1];
+ }
+ else {
+ vertexCos[iter][1] += delta;
+ }
+ break;
+ case MOD_DISP_DIR_Z:
+ if (use_global_direction) {
+ vertexCos[iter][0] += delta * data->local_mat[0][2];
+ vertexCos[iter][1] += delta * data->local_mat[1][2];
+ vertexCos[iter][2] += delta * data->local_mat[2][2];
+ }
+ else {
+ vertexCos[iter][2] += delta;
+ }
+ break;
+ case MOD_DISP_DIR_RGB_XYZ:
+ local_vec[0] = texres.tr - dmd->midlevel;
+ local_vec[1] = texres.tg - dmd->midlevel;
+ local_vec[2] = texres.tb - dmd->midlevel;
+ if (use_global_direction) {
+ mul_transposed_mat3_m4_v3(data->local_mat, local_vec);
+ }
+ mul_v3_fl(local_vec, strength);
+ add_v3_v3(vertexCos[iter], local_vec);
+ break;
+ case MOD_DISP_DIR_NOR:
+ vertexCos[iter][0] += delta * (mvert[iter].no[0] / 32767.0f);
+ vertexCos[iter][1] += delta * (mvert[iter].no[1] / 32767.0f);
+ vertexCos[iter][2] += delta * (mvert[iter].no[2] / 32767.0f);
+ break;
+ case MOD_DISP_DIR_CLNOR:
+ madd_v3_v3fl(vertexCos[iter], vert_clnors[iter], delta);
+ break;
+ }
+}
+
/* dm must be a CDDerivedMesh */
static void displaceModifier_do(
DisplaceModifierData *dmd, Object *ob,
DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
- int i;
MVert *mvert;
MDeformVert *dvert;
int direction = dmd->direction;
int defgrp_index;
float (*tex_co)[3];
float weight = 1.0f; /* init value unused but some compilers may complain */
- const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */
float (*vert_clnors)[3] = NULL;
- float local_mat[4][4];
+ float local_mat[4][4] = {0};
const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
@@ -234,81 +345,25 @@ static void displaceModifier_do(
copy_m4_m4(local_mat, ob->obmat);
}
- for (i = 0; i < numVerts; i++) {
- TexResult texres;
- float strength = dmd->strength;
- float delta;
- float local_vec[3];
-
- if (dvert) {
- weight = defvert_find_weight(dvert + i, defgrp_index);
- if (weight == 0.0f) continue;
- }
-
- if (dmd->texture) {
- texres.nor = NULL;
- BKE_texture_get_value(dmd->modifier.scene, dmd->texture, tex_co[i], &texres, false);
- delta = texres.tin - dmd->midlevel;
- }
- else {
- delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */
- }
+ DisplaceUserdata data = {NULL};
+ data.dmd = dmd;
+ data.dvert = dvert;
+ data.weight = weight;
+ data.defgrp_index = defgrp_index;
+ data.direction = direction;
+ data.use_global_direction = use_global_direction;
+ data.tex_co = tex_co;
+ data.vertexCos = vertexCos;
+ copy_m4_m4(data.local_mat, local_mat);
+ data.mvert = mvert;
+ data.vert_clnors = vert_clnors;
+ if (dmd->texture != NULL) {
+ data.pool = BKE_image_pool_new();
+ }
+ BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512);
- if (dvert) strength *= weight;
-
- delta *= strength;
- CLAMP(delta, -10000, 10000);
-
- switch (direction) {
- case MOD_DISP_DIR_X:
- if (use_global_direction) {
- vertexCos[i][0] += delta * local_mat[0][0];
- vertexCos[i][1] += delta * local_mat[1][0];
- vertexCos[i][2] += delta * local_mat[2][0];
- }
- else {
- vertexCos[i][0] += delta;
- }
- break;
- case MOD_DISP_DIR_Y:
- if (use_global_direction) {
- vertexCos[i][0] += delta * local_mat[0][1];
- vertexCos[i][1] += delta * local_mat[1][1];
- vertexCos[i][2] += delta * local_mat[2][1];
- }
- else {
- vertexCos[i][1] += delta;
- }
- break;
- case MOD_DISP_DIR_Z:
- if (use_global_direction) {
- vertexCos[i][0] += delta * local_mat[0][2];
- vertexCos[i][1] += delta * local_mat[1][2];
- vertexCos[i][2] += delta * local_mat[2][2];
- }
- else {
- vertexCos[i][2] += delta;
- }
- break;
- case MOD_DISP_DIR_RGB_XYZ:
- local_vec[0] = texres.tr - dmd->midlevel;
- local_vec[1] = texres.tg - dmd->midlevel;
- local_vec[2] = texres.tb - dmd->midlevel;
- if (use_global_direction) {
- mul_transposed_mat3_m4_v3(local_mat, local_vec);
- }
- mul_v3_fl(local_vec, strength);
- add_v3_v3(vertexCos[i], local_vec);
- break;
- case MOD_DISP_DIR_NOR:
- vertexCos[i][0] += delta * (mvert[i].no[0] / 32767.0f);
- vertexCos[i][1] += delta * (mvert[i].no[1] / 32767.0f);
- vertexCos[i][2] += delta * (mvert[i].no[2] / 32767.0f);
- break;
- case MOD_DISP_DIR_CLNOR:
- madd_v3_v3fl(vertexCos[i], vert_clnors[i], delta);
- break;
- }
+ if (data.pool != NULL) {
+ BKE_image_pool_free(data.pool);
}
if (tex_co) {
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index ee6df153905..794d8bf6951 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -153,15 +153,15 @@ static void foreachIDLink(ModifierData *md, Object *ob,
DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
for (; surface; surface = surface->next) {
- walk(userData, ob, (ID **)&surface->brush_group, IDWALK_NOP);
- walk(userData, ob, (ID **)&surface->init_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&surface->brush_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&surface->init_texture, IDWALK_CB_USER);
if (surface->effector_weights) {
- walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_CB_NOP);
}
}
}
if (pmd->brush) {
- walk(userData, ob, (ID **)&pmd->brush->mat, IDWALK_USER);
+ walk(userData, ob, (ID **)&pmd->brush->mat, IDWALK_CB_USER);
}
}
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index dea1f9d8d4c..24ce2e3cc8e 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -1001,8 +1001,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
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;
@@ -1010,6 +1008,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (psys->part == NULL || psys->particles == NULL) return derivedData;
if (psmd->dm_final == NULL) return derivedData;
+ DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+
/* 1. find faces to be exploded if needed */
if (emd->facepa == NULL ||
psmd->flag & eParticleSystemFlag_Pars ||
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index bed25fa82db..35e9afe722b 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -109,7 +109,7 @@ static void updateDepsgraph(ModifierData *md,
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
if (fluidmd && fluidmd->fss) {
if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
Object *ob1 = base->object;
if (ob1 != ob) {
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 13d94abc92d..210e91d159a 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -115,7 +115,7 @@ static void foreachObjectLink(
{
HookModifierData *hmd = (HookModifierData *) md;
- walk(userData, ob, &hmd->object, IDWALK_NOP);
+ walk(userData, ob, &hmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 292c2db61f8..2e02ab29d5f 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -88,7 +88,7 @@ static void foreachObjectLink(
{
LatticeModifierData *lmd = (LatticeModifierData *) md;
- walk(userData, ob, &lmd->object, IDWALK_NOP);
+ walk(userData, ob, &lmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 7cb2f2c25d5..1c4406e1a4f 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -74,7 +74,7 @@ static void foreachObjectLink(
ObjectWalkFunc walk, void *userData)
{
MaskModifierData *mmd = (MaskModifierData *)md;
- walk(userData, ob, &mmd->ob_arm, IDWALK_NOP);
+ walk(userData, ob, &mmd->ob_arm, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 27782b05cd2..ed1f5e8938b 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -119,7 +119,7 @@ static void foreachObjectLink(
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
- walk(userData, ob, &mmd->object, IDWALK_NOP);
+ walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 985c365bb69..0b9298a26a6 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -151,7 +151,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md;
- walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_USER);
+ walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_CB_USER);
}
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 9fdd75aeb68..8c01c560e75 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -72,7 +72,7 @@ static void foreachObjectLink(
{
MirrorModifierData *mmd = (MirrorModifierData *) md;
- walk(userData, ob, &mmd->mirror_ob, IDWALK_NOP);
+ walk(userData, ob, &mmd->mirror_ob, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index eefca658305..b73f1074bc1 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -501,7 +501,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
NormalEditModifierData *enmd = (NormalEditModifierData *) md;
- walk(userData, ob, &enmd->target, IDWALK_NOP);
+ walk(userData, ob, &enmd->target, IDWALK_CB_NOP);
}
static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index a468cc6600d..9d8e1e181a4 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -127,7 +127,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
- walk(userData, ob, &pimd->ob, IDWALK_NOP);
+ walk(userData, ob, &pimd->ob, IDWALK_CB_NOP);
}
static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index a834d1b5cae..1273a3a6e09 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -1075,7 +1075,7 @@ static void foreachObjectLink(
{
ScrewModifierData *ltmd = (ScrewModifierData *) md;
- walk(userData, ob, &ltmd->ob_axis, IDWALK_NOP);
+ walk(userData, ob, &ltmd->ob_axis, IDWALK_CB_NOP);
}
ModifierTypeInfo modifierType_Screw = {
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 29bce2ef3a4..d6d8c931c35 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -101,8 +101,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *) md;
- walk(userData, ob, &smd->target, IDWALK_NOP);
- walk(userData, ob, &smd->auxTarget, IDWALK_NOP);
+ walk(userData, ob, &smd->target, IDWALK_CB_NOP);
+ walk(userData, ob, &smd->auxTarget, IDWALK_CB_NOP);
}
static void deformVerts(ModifierData *md, Object *ob,
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 118d0117361..7c12de9059e 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -290,7 +290,7 @@ static void foreachObjectLink(
ObjectWalkFunc walk, void *userData)
{
SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
- walk(userData, ob, &smd->origin, IDWALK_NOP);
+ walk(userData, ob, &smd->origin, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index 637ed3ee390..8ba39819b5e 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -152,17 +152,17 @@ static void foreachIDLink(ModifierData *md, Object *ob,
SmokeModifierData *smd = (SmokeModifierData *) md;
if (smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
- walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_NOP);
- walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_NOP);
- walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_CB_NOP);
if (smd->domain->effector_weights) {
- walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_CB_NOP);
}
}
if (smd->type == MOD_SMOKE_TYPE_FLOW && smd->flow) {
- walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_CB_USER);
}
}
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 54c25b687e1..fdbf4f47ce8 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -92,7 +92,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
int i;
for (i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
- walk(userData, ob, &umd->projectors[i], IDWALK_NOP);
+ walk(userData, ob, &umd->projectors[i], IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -100,7 +100,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
UVProjectModifierData *umd = (UVProjectModifierData *) md;
- walk(userData, ob, (ID **)&umd->image, IDWALK_USER);
+ walk(userData, ob, (ID **)&umd->image, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 2ac6892b7b8..072267fc505 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -221,8 +221,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
UVWarpModifierData *umd = (UVWarpModifierData *) md;
- walk(userData, ob, &umd->object_dst, IDWALK_NOP);
- walk(userData, ob, &umd->object_src, IDWALK_NOP);
+ walk(userData, ob, &umd->object_dst, IDWALK_CB_NOP);
+ walk(userData, ob, &umd->object_src, IDWALK_CB_NOP);
}
static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 13ce72ee2f5..8c6b94e5c79 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -116,16 +116,16 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
WarpModifierData *wmd = (WarpModifierData *) md;
- walk(userData, ob, &wmd->object_from, IDWALK_NOP);
- walk(userData, ob, &wmd->object_to, IDWALK_NOP);
- walk(userData, ob, &wmd->map_object, IDWALK_NOP);
+ walk(userData, ob, &wmd->object_from, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->object_to, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WarpModifierData *wmd = (WarpModifierData *) md;
- walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 291913675c3..a60607cf372 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -111,8 +111,8 @@ static void foreachObjectLink(
{
WaveModifierData *wmd = (WaveModifierData *) md;
- walk(userData, ob, &wmd->objectcenter, IDWALK_NOP);
- walk(userData, ob, &wmd->map_object, IDWALK_NOP);
+ walk(userData, ob, &wmd->objectcenter, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -120,7 +120,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
WaveModifierData *wmd = (WaveModifierData *) md;
- walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 585b223d436..57a10a24411 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -126,14 +126,14 @@ static bool dependsOnTime(ModifierData *md)
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index a6adf72e4eb..9ab8fb4e0ff 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -175,14 +175,14 @@ static bool dependsOnTime(ModifierData *md)
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index b26cbc3a7d3..126a1f951ca 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -325,15 +325,15 @@ static bool dependsOnTime(ModifierData *md)
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- walk(userData, ob, &wmd->proximity_ob_target, IDWALK_NOP);
- walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
+ walk(userData, ob, &wmd->proximity_ob_target, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index df1c4155a6d..b8c9b3ff9e9 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -174,6 +174,7 @@ static eSpace_Type rna_Space_refine_reverse(StructRNA *srna)
if (srna == &RNA_SpaceConsole) return SPACE_CONSOLE;
if (srna == &RNA_SpaceUserPreferences) return SPACE_USERPREF;
if (srna == &RNA_SpaceClipEditor) return SPACE_CLIP;
+ if (srna == &RNA_SpaceCollectionManager) return SPACE_COLLECTIONS;
return SPACE_EMPTY;
}
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 1037c83815c..72705ffb3fb 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -263,7 +263,7 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
}
data_cb.id_curr = id;
- BKE_library_foreach_ID_link(id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_NOP);
+ BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP);
if (data_cb.py_id_curr) {
Py_DECREF(data_cb.py_id_curr);
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
index 50dd4618166..48230a723d2 100644
--- a/source/blender/python/intern/gpu.c
+++ b/source/blender/python/intern/gpu.c
@@ -138,6 +138,7 @@ static PyObject *PyInit_gpu(void)
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_MIR);
/* -------------------------------------------------------------------- */
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 9e40ab02ee4..27fa119bc88 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -35,6 +35,7 @@ set(INC
../makesdna
../makesrna
../physics
+ ../draw
../../../intern/guardedalloc
../../../intern/mikktspace
../../../intern/smoke/extern
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index f83a210275f..f1b3534b40a 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -39,6 +39,8 @@
struct bNode;
struct bNodeTree;
+struct CollectionEngineSettings;
+struct Main;
struct Object;
struct Render;
struct RenderData;
@@ -63,6 +65,7 @@ struct BakePixel;
#define RE_USE_TEXTURE_PREVIEW 128
#define RE_USE_SHADING_NODES_CUSTOM 256
#define RE_USE_SPHERICAL_STEREO 512
+#define RE_USE_OGL_PIPELINE 1024
/* RenderEngine.flag */
#define RE_ENGINE_ANIMATION 1
@@ -97,6 +100,8 @@ typedef struct RenderEngineType {
void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
+ void (*collection_settings_create)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
+
/* RNA integration */
ExtensionRNA ext;
} RenderEngineType;
@@ -164,6 +169,7 @@ void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe)
void RE_engines_init(void);
void RE_engines_exit(void);
+void RE_engines_register(struct Main *bmain, RenderEngineType *render_type);
RenderEngineType *RE_engines_find(const char *idname);
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 263ea3d4ef2..094e62e6ceb 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -4977,7 +4977,7 @@ static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, in
static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset)
{
- Base *base;
+ BaseLegacy *base;
Object *ob;
Group *group;
ObjectInstanceRen *obi;
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index d97e18d6511..7de20ab2056 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -247,7 +247,7 @@ static void envmap_transmatrix(float mat[4][4], int part)
static void env_set_imats(Render *re)
{
- Base *base;
+ BaseLegacy *base;
float mat[4][4];
base = re->scene->base.first;
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index fd9d95c63b6..1744d88a14f 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -45,6 +45,7 @@
#include "BKE_camera.h"
#include "BKE_global.h"
#include "BKE_colortools.h"
+#include "BKE_layer.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -58,6 +59,8 @@
#include "RE_pipeline.h"
#include "RE_bake.h"
+#include "DRW_engine.h"
+
#include "initrender.h"
#include "renderpipeline.h"
#include "render_types.h"
@@ -68,7 +71,7 @@
static RenderEngineType internal_render_type = {
NULL, NULL,
"BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -77,7 +80,7 @@ static RenderEngineType internal_render_type = {
static RenderEngineType internal_game_type = {
NULL, NULL,
"BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -87,16 +90,21 @@ ListBase R_engines = {NULL, NULL};
void RE_engines_init(void)
{
- BLI_addtail(&R_engines, &internal_render_type);
+ RE_engines_register(NULL, &internal_render_type);
#ifdef WITH_GAMEENGINE
- BLI_addtail(&R_engines, &internal_game_type);
+ RE_engines_register(NULL, &internal_game_type);
#endif
+ DRW_engines_init();
}
void RE_engines_exit(void)
{
RenderEngineType *type, *next;
+ DRW_engines_free();
+
+ BKE_layer_collection_engine_settings_callback_free();
+
for (type = R_engines.first; type; type = next) {
next = type->next;
@@ -111,6 +119,14 @@ void RE_engines_exit(void)
}
}
+void RE_engines_register(Main *bmain, RenderEngineType *render_type)
+{
+ if (render_type->collection_settings_create) {
+ BKE_layer_collection_engine_settings_callback_register(bmain, render_type->idname, render_type->collection_settings_create);
+ }
+ BLI_addtail(&R_engines, render_type);
+}
+
RenderEngineType *RE_engines_find(const char *idname)
{
RenderEngineType *type;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 52eca5f7005..34966e1b111 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -2015,7 +2015,7 @@ bool RE_allow_render_generic_object(Object *ob)
static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
{
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
for (SETLOOPER(scene, sce_iter, base)) {
Object *object = base->object;
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 6dbcf474e77..1022aeeec66 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -361,6 +361,7 @@ static void init_frame_smoke(VoxelData *vd, int cfra)
#else // WITH_SMOKE
(void)vd;
+ (void)cfra;
vd->dataset = NULL;
#endif
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 3bed4dac2cf..49e70b4f200 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -364,6 +364,7 @@ typedef struct wmNotifier {
#define ND_SPACE_CHANGED (18<<16) /*sent to a new editor type after it's replaced an old one*/
#define ND_SPACE_CLIP (19<<16)
#define ND_SPACE_FILE_PREVIEW (20<<16)
+#define ND_SPACE_COLLECTIONS (21<<16)
/* subtype, 256 entries too */
#define NOTE_SUBTYPE 0x0000FF00
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 85a313b3f81..2d1dcd7f3c9 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -361,8 +361,8 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
drag_rect_minmax(rect, x, y, x + w, y + iconsize);
}
else {
- glColor4ub(255, 255, 255, 255);
- UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag));
+ const unsigned char col[] = {255, 255, 255, 255};
+ UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag), col);
}
/* operator name with roundbox */
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index e201fa433d4..4179ac7f993 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -1861,6 +1861,10 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
else if (STRPREFIX(opname, "OUTLINER_OT")) {
km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0);
}
+ /* Layer Manager */
+ else if (STRPREFIX(opname, "COLLECTIONS_OT")) {
+ km = WM_keymap_find_all(C, "Collection Manager", sl->spacetype, 0);
+ }
/* Transform */
else if (STRPREFIX(opname, "TRANSFORM_OT")) {
/* check for relevant editor */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index a8abc3bb54f..6591005b5f3 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3950,8 +3950,12 @@ static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
}
}
-static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int UNUSED(cd_flag))
+static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
PreviewsIDEnsureData *data = userdata;
ID *id = *idptr;
@@ -3984,7 +3988,7 @@ static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op))
preview_id_data.scene = scene;
id = (ID *)scene;
- BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
+ BKE_library_foreach_ID_link(NULL, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
}
/* Check a last time for ID not used (fake users only, in theory), and
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 6b615f5a121..0acc66ad9b0 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -45,6 +45,7 @@ struct ARegion;
struct ARegionType;
struct BMEditMesh;
struct Base;
+struct BaseLegacy;
struct bContext;
struct BoundBox;
struct Brush;
@@ -185,6 +186,7 @@ struct wmWindowManager;
#include "../blender/render/extern/include/RE_pipeline.h"
#include "../blender/render/extern/include/RE_render_ext.h"
#include "../blender/render/extern/include/RE_shader_ext.h"
+#include "../blender/draw/DRW_engine.h"
#include "../blender/windowmanager/WM_api.h"
@@ -237,13 +239,13 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name)
void RE_texture_rng_init() RET_NONE
void RE_texture_rng_exit() RET_NONE
-bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;}
+bool RE_layers_have_name(struct RenderResult *result) RET_ZERO
const char *RE_engine_active_view_get(struct RenderEngine *engine) RET_NULL
-void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);}
-void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) {STUB_ASSERT(0);}
+void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) RET_NONE
+void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) RET_NONE
float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo) RET_ZERO
int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO
-void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);}
+void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE
struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
bool RE_HasFakeLayer(RenderResult *res) RET_ZERO
@@ -462,17 +464,17 @@ void ED_node_texture_default(const struct bContext *C, struct Tex *tex) RET_NONE
void ED_node_tag_update_id(struct ID *id) RET_NONE
void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node) RET_NONE
void ED_node_tree_update(const struct bContext *C) RET_NONE
-void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo){}
-void ED_init_custom_node_type(struct bNodeType *ntype){}
-void ED_init_custom_node_socket_type(struct bNodeSocketType *stype){}
+void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo) RET_NONE
+void ED_init_custom_node_type(struct bNodeType *ntype) RET_NONE
+void ED_init_custom_node_socket_type(struct bNodeSocketType *stype) RET_NONE
void ED_init_standard_node_socket_type(struct bNodeSocketType *stype) RET_NONE
void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype) RET_NONE
-int ED_node_tree_path_length(struct SpaceNode *snode){return 0;}
-void ED_node_tree_path_get(struct SpaceNode *snode, char *value){}
-void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length){}
-void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from){}
-void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode){}
-void ED_node_tree_pop(struct SpaceNode *snode){}
+int ED_node_tree_path_length(struct SpaceNode *snode) RET_ZERO
+void ED_node_tree_path_get(struct SpaceNode *snode, char *value) RET_NONE
+void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length) RET_NONE
+void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from) RET_NONE
+void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode) RET_NONE
+void ED_node_tree_pop(struct SpaceNode *snode) RET_NONE
int ED_view3d_scene_layer_set(int lay, const int *values, int *active) RET_ZERO
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip) RET_NONE
void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) RET_NONE
@@ -485,7 +487,8 @@ void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View
void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE
struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL
-void ED_base_object_select(struct Base *base, short mode) RET_NONE
+void ED_base_object_select(struct BaseLegacy *base, short mode) RET_NONE
+void ED_object_base_select(struct Base *base, short mode) RET_NONE
bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain, struct Object *ob, struct ModifierData *md) RET_ZERO
struct ModifierData *ED_object_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name, int type) RET_ZERO
void ED_object_modifier_clear(struct Main *bmain, struct Object *ob) RET_NONE
@@ -506,7 +509,7 @@ void uiLayoutSetAlignment(uiLayout *layout, char alignment) RET_NONE
void uiLayoutSetScaleX(struct uiLayout *layout, float scale) RET_NONE
void uiLayoutSetScaleY(struct uiLayout *layout, float scale) RET_NONE
void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale) RET_NONE
-void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base) RET_NONE
+void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *base) RET_NONE
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface) RET_NONE
void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE
void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count) RET_NONE
@@ -661,6 +664,7 @@ void RE_ReleaseResultImage(struct Render *re) RET_NONE
int RE_engine_test_break(struct RenderEngine *engine) RET_ZERO
void RE_engines_init() RET_NONE
void RE_engines_exit() RET_NONE
+void RE_engines_register(struct Main *bmain, RenderEngineType *render_type) RET_NONE
void RE_engine_report(struct RenderEngine *engine, int type, const char *msg) RET_NONE
ListBase R_engines = {NULL, NULL};
void RE_engine_free(struct RenderEngine *engine) RET_NONE
@@ -670,13 +674,16 @@ struct RenderEngine *RE_engine_create(struct RenderEngineType *type) RET_NULL
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) RET_NONE
void RE_FreePersistentData(void) RET_NONE
void RE_point_density_cache(struct Scene *scene, struct PointDensity *pd, const bool use_render_params) RET_NONE
-void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE;
-void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE;
-void RE_point_density_free(struct PointDensity *pd) RET_NONE;
+void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE
+void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE
+void RE_point_density_free(struct PointDensity *pd) RET_NONE
void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
void RE_FreeAllPersistentData(void) RET_NONE
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
+/* Draw */
+void *DRW_render_settings_get(struct Scene *scene, const char *engine_name) RET_NULL
+
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
void WM_operatortype_iter(struct GHashIterator *ghi) RET_NONE
@@ -754,7 +761,7 @@ void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *
void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO
struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL
-void BPY_context_update(struct bContext *C) RET_NONE;
+void BPY_context_update(struct bContext *C) RET_NONE
const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) RET_ARG(msgid)
/* intern/dualcon */
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 4751e60996d..2aa0145d1f3 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -394,7 +394,7 @@ static void SetDefaultLightMode(Scene* scene)
{
default_light_mode = false;
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
for (SETLOOPER(scene, sce_iter, base))
{
@@ -1736,11 +1736,11 @@ static void UNUSED_FUNCTION(print_active_constraints2)(Object *ob) //not used, u
static void blenderSceneSetBackground(Scene *blenderscene)
{
Scene *it;
- Base *base;
+ BaseLegacy *base;
for (SETLOOPER(blenderscene, it, base)) {
base->object->lay = base->lay;
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
}
}
@@ -1911,7 +1911,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
Scene *blenderscene = kxscene->GetBlenderScene();
// for SETLOOPER
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
// Get the frame settings of the canvas.
// Get the aspect ratio of the canvas as designed by the user.
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 5f490747c2b..b2a480e99ca 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -34,6 +34,7 @@
#endif
#include <stdio.h>
+#include "DNA_scene_types.h"
#include "KX_Light.h"
#include "KX_Camera.h"
@@ -44,7 +45,6 @@
#include "KX_PyMath.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "DNA_lamp_types.h"
#include "BKE_scene.h"
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index b446acd6e63..469f2d62b76 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -38,7 +38,7 @@
struct GPULamp;
struct Scene;
-struct Base;
+struct BaseLegacy;
class KX_Camera;
class RAS_IRasterizer;
class RAS_ILightObject;
@@ -51,7 +51,7 @@ protected:
RAS_ILightObject* m_lightobj;
class RAS_IRasterizer* m_rasterizer; //needed for registering and replication of lightobj
Scene* m_blenderscene;
- Base* m_base;
+ BaseLegacy* m_base;
public:
KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,RAS_IRasterizer* rasterizer,RAS_ILightObject* lightobj, bool glsl);
diff --git a/source/tools b/source/tools
-Subproject 6bbb68073bfa11e94bb0b3623db38f847037add
+Subproject b11375e89061303401376f7aeae42ac2fd64692
diff --git a/tests/gtests/blenlib/BLI_array_store_test.cc b/tests/gtests/blenlib/BLI_array_store_test.cc
index b71dc4575f1..5af6e639e64 100644
--- a/tests/gtests/blenlib/BLI_array_store_test.cc
+++ b/tests/gtests/blenlib/BLI_array_store_test.cc
@@ -280,8 +280,8 @@ static void testbuffer_run_tests_single(
BArrayStore *bs, ListBase *lb)
{
testbuffer_list_store_populate(bs, lb);
- EXPECT_EQ(true, testbuffer_list_validate(lb));
- EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ EXPECT_TRUE(testbuffer_list_validate(lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
#ifdef DEBUG_PRINT
print_mem_saved("data", bs);
#endif
@@ -326,7 +326,7 @@ TEST(array_store, NopState)
BArrayStore *bs = BLI_array_store_create(1, 32);
const unsigned char data[] = "test";
BArrayState *state = BLI_array_store_state_add(bs, data, sizeof(data) - 1, NULL);
- EXPECT_EQ(sizeof(data) - 1, BLI_array_store_state_size_get(state));
+ EXPECT_EQ(BLI_array_store_state_size_get(state), sizeof(data) - 1);
BLI_array_store_state_remove(bs, state);
BLI_array_store_destroy(bs);
}
@@ -340,7 +340,7 @@ TEST(array_store, Single)
size_t data_dst_len;
data_dst = (char *)BLI_array_store_state_data_get_alloc(state, &data_dst_len);
EXPECT_STREQ(data_src, data_dst);
- EXPECT_EQ(sizeof(data_src), data_dst_len);
+ EXPECT_EQ(data_dst_len, sizeof(data_src));
BLI_array_store_destroy(bs);
MEM_freeN((void *)data_dst);
}
@@ -354,8 +354,8 @@ TEST(array_store, DoubleNop)
BArrayState *state_a = BLI_array_store_state_add(bs, data_src, sizeof(data_src), NULL);
BArrayState *state_b = BLI_array_store_state_add(bs, data_src, sizeof(data_src), state_a);
- EXPECT_EQ(sizeof(data_src), BLI_array_store_calc_size_compacted_get(bs));
- EXPECT_EQ(sizeof(data_src) * 2, BLI_array_store_calc_size_expanded_get(bs));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), sizeof(data_src));
+ EXPECT_EQ(BLI_array_store_calc_size_expanded_get(bs), sizeof(data_src) * 2);
size_t data_dst_len;
@@ -367,7 +367,7 @@ TEST(array_store, DoubleNop)
EXPECT_STREQ(data_src, data_dst);
MEM_freeN((void *)data_dst);
- EXPECT_EQ(sizeof(data_src), data_dst_len);
+ EXPECT_EQ(data_dst_len, sizeof(data_src));
BLI_array_store_destroy(bs);
}
@@ -382,8 +382,8 @@ TEST(array_store, DoubleDiff)
BArrayState *state_b = BLI_array_store_state_add(bs, data_src_b, sizeof(data_src_b), state_a);
size_t data_dst_len;
- EXPECT_EQ(sizeof(data_src_a) * 2, BLI_array_store_calc_size_compacted_get(bs));
- EXPECT_EQ(sizeof(data_src_a) * 2, BLI_array_store_calc_size_expanded_get(bs));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), sizeof(data_src_a) * 2);
+ EXPECT_EQ(BLI_array_store_calc_size_expanded_get(bs), sizeof(data_src_a) * 2);
data_dst = (char *)BLI_array_store_state_data_get_alloc(state_a, &data_dst_len);
EXPECT_STREQ(data_src_a, data_dst);
@@ -423,19 +423,19 @@ TEST(array_store, TextDupeIncreaseDecrease)
/* forward */
testbuffer_list_store_populate(bs, &lb);
- EXPECT_EQ(true, testbuffer_list_validate(&lb));
- EXPECT_EQ(true, BLI_array_store_is_valid(bs));
- EXPECT_EQ(strlen(D), BLI_array_store_calc_size_compacted_get(bs));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), strlen(D));
testbuffer_list_store_clear(bs, &lb);
BLI_listbase_reverse(&lb);
/* backwards */
testbuffer_list_store_populate(bs, &lb);
- EXPECT_EQ(true, testbuffer_list_validate(&lb));
- EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
/* larger since first block doesn't de-duplicate */
- EXPECT_EQ(strlen(D) * 4, BLI_array_store_calc_size_compacted_get(bs));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), strlen(D) * 4);
#undef D
testbuffer_list_free(&lb); \
@@ -708,7 +708,7 @@ static void random_chunk_mutate_helper(
testbuffer_run_tests_single(bs, &lb);
size_t expected_size = chunks_per_buffer * chunk_count * stride;
- EXPECT_EQ(expected_size, BLI_array_store_calc_size_compacted_get(bs));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), expected_size);
BLI_array_store_destroy(bs);
@@ -782,8 +782,8 @@ TEST(array_store, PlainTextFiles)
/* forwards */
testbuffer_list_store_populate(bs, &lb);
- EXPECT_EQ(true, testbuffer_list_validate(&lb));
- EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
#ifdef DEBUG_PRINT
print_mem_saved("source code forward", bs);
#endif
@@ -793,8 +793,8 @@ TEST(array_store, PlainTextFiles)
/* backwards */
testbuffer_list_store_populate(bs, &lb);
- EXPECT_EQ(true, testbuffer_list_validate(&lb));
- EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
#ifdef DEBUG_PRINT
print_mem_saved("source code backwards", bs);
#endif
diff --git a/tests/gtests/blenlib/BLI_array_utils_test.cc b/tests/gtests/blenlib/BLI_array_utils_test.cc
index eabf5bc72cf..518cd097326 100644
--- a/tests/gtests/blenlib/BLI_array_utils_test.cc
+++ b/tests/gtests/blenlib/BLI_array_utils_test.cc
@@ -45,50 +45,50 @@ TEST(array_utils, ReverseInt4)
TEST(array_utils, FindIndexStringEmpty)
{
char data[] = "", find = '0';
- EXPECT_EQ(-1, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(-1, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), -1);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), -1);
}
TEST(array_utils, FindIndexStringSingle)
{
char data[] = "0", find = '0';
- EXPECT_EQ(0, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(0, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), 0);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), 0);
}
TEST(array_utils, FindIndexStringSingleMissing)
{
char data[] = "1", find = '0';
- EXPECT_EQ(-1, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(-1, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), -1);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), -1);
}
TEST(array_utils, FindIndexString4)
{
char data[] = "0123", find = '3';
- EXPECT_EQ(3, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), 3);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), 3);
}
TEST(array_utils, FindIndexInt4)
{
int data[] = {0, 1, 2, 3}, find = 3;
- EXPECT_EQ(3, BLI_array_findindex(data, ARRAY_SIZE(data), &find));
- EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 3);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 3);
}
TEST(array_utils, FindIndexInt4_DupeEnd)
{
int data[] = {0, 1, 2, 0}, find = 0;
- EXPECT_EQ(0, BLI_array_findindex(data, ARRAY_SIZE(data), &find));
- EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 0);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 3);
}
TEST(array_utils, FindIndexInt4_DupeMid)
{
int data[] = {1, 0, 0, 3}, find = 0;
- EXPECT_EQ(1, BLI_array_findindex(data, ARRAY_SIZE(data), &find));
- EXPECT_EQ(2, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 1);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 2);
}
TEST(array_utils, FindIndexPointer)
@@ -102,18 +102,18 @@ TEST(array_utils, FindIndexPointer)
#define STACK_PUSH_AND_CHECK_FORWARD(v, i) { \
STACK_PUSH(data, v); \
- EXPECT_EQ(i, BLI_array_findindex(data, STACK_SIZE(data), &(v))); \
+ EXPECT_EQ(BLI_array_findindex(data, STACK_SIZE(data), &(v)), i); \
} ((void)0)
#define STACK_PUSH_AND_CHECK_BACKWARD(v, i) { \
STACK_PUSH(data, v); \
- EXPECT_EQ(i, BLI_array_rfindindex(data, STACK_SIZE(data), &(v))); \
+ EXPECT_EQ(BLI_array_rfindindex(data, STACK_SIZE(data), &(v)), i); \
} ((void)0)
#define STACK_PUSH_AND_CHECK_BOTH(v, i) { \
STACK_PUSH(data, v); \
- EXPECT_EQ(i, BLI_array_findindex(data, STACK_SIZE(data), &(v))); \
- EXPECT_EQ(i, BLI_array_rfindindex(data, STACK_SIZE(data), &(v))); \
+ EXPECT_EQ(BLI_array_findindex(data, STACK_SIZE(data), &(v)), i); \
+ EXPECT_EQ(BLI_array_rfindindex(data, STACK_SIZE(data), &(v)), i); \
} ((void)0)
STACK_PUSH_AND_CHECK_BOTH(a, 0);
diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
index fb32cb3f0a5..924c84d72d0 100644
--- a/tests/gtests/blenlib/BLI_ghash_performance_test.cc
+++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
@@ -118,21 +118,21 @@ static void str_ghash_tests(GHash *ghash, const char *id)
TIMEIT_START(string_lookup);
v = BLI_ghash_lookup(ghash, data_bis);
- EXPECT_EQ(data_bis[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), data_bis[0]);
for (p = w = c = data_bis; *c; c++) {
if (*c == '.') {
*c = '\0';
v = BLI_ghash_lookup(ghash, w);
- EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), w[0]);
v = BLI_ghash_lookup(ghash, p);
- EXPECT_EQ(p[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), p[0]);
p = w = c + 1;
}
else if (*c == ' ') {
*c = '\0';
v = BLI_ghash_lookup(ghash, w);
- EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), w[0]);
w = c + 1;
}
}
@@ -195,7 +195,7 @@ static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr
while (i--) {
void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(i));
- EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), i);
}
TIMEIT_END(int_lookup);
@@ -214,7 +214,7 @@ static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr
TIMEIT_END(int_pop);
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
BLI_ghash_free(ghash, NULL, NULL);
@@ -292,7 +292,7 @@ static void randint_ghash_tests(GHash *ghash, const char *id, const unsigned int
for (i = nbr, dt = data; i--; dt++) {
void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt));
- EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *dt);
}
TIMEIT_END(int_lookup);
@@ -403,7 +403,7 @@ static void int4_ghash_tests(GHash *ghash, const char *id, const unsigned int nb
for (i = nbr, dt = data; i--; dt++) {
void *v = BLI_ghash_lookup(ghash, (void *)(*dt));
- EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), i);
}
TIMEIT_END(int_v4_lookup);
@@ -469,7 +469,7 @@ static void multi_small_ghash_tests_one(GHash *ghash, RNG *rng, const unsigned i
for (i = nbr, dt = data; i--; dt++) {
void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt));
- EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *dt);
}
BLI_ghash_clear(ghash, NULL, NULL);
diff --git a/tests/gtests/blenlib/BLI_ghash_test.cc b/tests/gtests/blenlib/BLI_ghash_test.cc
index ffbe5f5547f..6d075e29114 100644
--- a/tests/gtests/blenlib/BLI_ghash_test.cc
+++ b/tests/gtests/blenlib/BLI_ghash_test.cc
@@ -62,11 +62,11 @@ TEST(ghash, InsertLookup)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*k));
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
BLI_ghash_free(ghash, NULL, NULL);
@@ -85,16 +85,16 @@ TEST(ghash, InsertRemove)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
bkt_size = BLI_ghash_buckets_size(ghash);
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
- EXPECT_EQ(bkt_size, BLI_ghash_buckets_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
+ EXPECT_EQ(BLI_ghash_buckets_size(ghash), bkt_size);
BLI_ghash_free(ghash, NULL, NULL);
}
@@ -113,15 +113,15 @@ TEST(ghash, InsertRemoveShrink)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
bkt_size = BLI_ghash_buckets_size(ghash);
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
EXPECT_LT(BLI_ghash_buckets_size(ghash), bkt_size);
BLI_ghash_free(ghash, NULL, NULL);
@@ -141,16 +141,16 @@ TEST(ghash, Copy)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
ghash_copy = BLI_ghash_copy(ghash, NULL, NULL);
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash_copy));
- EXPECT_EQ(BLI_ghash_buckets_size(ghash), BLI_ghash_buckets_size(ghash_copy));
+ EXPECT_EQ(BLI_ghash_size(ghash_copy), TESTCASE_SIZE);
+ EXPECT_EQ(BLI_ghash_buckets_size(ghash_copy), BLI_ghash_buckets_size(ghash));
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_lookup(ghash_copy, SET_UINT_IN_POINTER(*k));
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
BLI_ghash_free(ghash, NULL, NULL);
@@ -171,7 +171,7 @@ TEST(ghash, Pop)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
GHashIterState pop_state = {0};
@@ -179,14 +179,14 @@ TEST(ghash, Pop)
void *k, *v;
bool success = BLI_ghash_pop(ghash, &pop_state, &k, &v);
EXPECT_EQ(k, v);
- EXPECT_EQ(success, true);
+ EXPECT_TRUE(success);
if (i % 2) {
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(i * 4), SET_UINT_IN_POINTER(i * 4));
}
}
- EXPECT_EQ((TESTCASE_SIZE - TESTCASE_SIZE / 2 + TESTCASE_SIZE / 4), BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), (TESTCASE_SIZE - TESTCASE_SIZE / 2 + TESTCASE_SIZE / 4));
{
void *k, *v;
@@ -194,7 +194,7 @@ TEST(ghash, Pop)
EXPECT_EQ(k, v);
}
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
BLI_ghash_free(ghash, NULL, NULL);
}
diff --git a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
index b35a1a809d6..109c925af4c 100644
--- a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
+++ b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
@@ -19,9 +19,9 @@ TEST(hash_mm2a, MM2ABasic)
BLI_hash_mm2a_init(&mm2, 0);
BLI_hash_mm2a_add(&mm2, (const unsigned char *)data, strlen(data));
#ifdef __LITTLE_ENDIAN__
- EXPECT_EQ(1633988145, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 1633988145);
#else
- EXPECT_EQ(959283772, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 959283772);
#endif
}
@@ -43,11 +43,11 @@ TEST(hash_mm2a, MM2AConcatenateStrings)
BLI_hash_mm2a_init(&mm2, 0);
BLI_hash_mm2a_add(&mm2, (const unsigned char *)data123, strlen(data123));
#ifdef __LITTLE_ENDIAN__
- EXPECT_EQ(1545105348, hash);
+ EXPECT_EQ(hash, 1545105348);
#else
- EXPECT_EQ(2604964730, hash);
+ EXPECT_EQ(hash, 2604964730);
#endif
- EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash);
}
TEST(hash_mm2a, MM2AIntegers)
@@ -67,9 +67,9 @@ TEST(hash_mm2a, MM2AIntegers)
BLI_hash_mm2a_add(&mm2, (const unsigned char *)ints, sizeof(ints));
/* Yes, same hash here on little and big endian. */
#ifdef __LITTLE_ENDIAN__
- EXPECT_EQ(405493096, hash);
+ EXPECT_EQ(hash, 405493096);
#else
- EXPECT_EQ(405493096, hash);
+ EXPECT_EQ(hash, 405493096);
#endif
- EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash);
}
diff --git a/tests/gtests/blenlib/BLI_listbase_test.cc b/tests/gtests/blenlib/BLI_listbase_test.cc
index 994b8f74541..4dac2d05bd8 100644
--- a/tests/gtests/blenlib/BLI_listbase_test.cc
+++ b/tests/gtests/blenlib/BLI_listbase_test.cc
@@ -74,25 +74,25 @@ TEST(listbase, FindLinkOrIndex)
/* Empty list */
BLI_listbase_clear(&lb);
- EXPECT_EQ(NULL, BLI_findlink(&lb, -1));
- EXPECT_EQ(NULL, BLI_findlink(&lb, 0));
- EXPECT_EQ(NULL, BLI_findlink(&lb, 1));
- EXPECT_EQ(NULL, BLI_rfindlink(&lb, -1));
- EXPECT_EQ(NULL, BLI_rfindlink(&lb, 0));
- EXPECT_EQ(NULL, BLI_rfindlink(&lb, 1));
- EXPECT_EQ(-1, BLI_findindex(&lb, link1));
+ EXPECT_EQ(BLI_findlink(&lb, -1), (void*)NULL);
+ EXPECT_EQ(BLI_findlink(&lb, 0), (void*)NULL);
+ EXPECT_EQ(BLI_findlink(&lb, 1), (void*)NULL);
+ EXPECT_EQ(BLI_rfindlink(&lb, -1), (void*)NULL);
+ EXPECT_EQ(BLI_rfindlink(&lb, 0), (void*)NULL);
+ EXPECT_EQ(BLI_rfindlink(&lb, 1), (void*)NULL);
+ EXPECT_EQ(BLI_findindex(&lb, link1), -1);
/* One link */
BLI_addtail(&lb, link1);
- EXPECT_EQ(link1, BLI_findlink(&lb, 0));
- EXPECT_EQ(link1, BLI_rfindlink(&lb, 0));
- EXPECT_EQ(0, BLI_findindex(&lb, link1));
+ EXPECT_EQ(BLI_findlink(&lb, 0), link1);
+ EXPECT_EQ(BLI_rfindlink(&lb, 0), link1);
+ EXPECT_EQ(BLI_findindex(&lb, link1), 0);
/* Two links */
BLI_addtail(&lb, link2);
- EXPECT_EQ(link2, BLI_findlink(&lb, 1));
- EXPECT_EQ(link2, BLI_rfindlink(&lb, 0));
- EXPECT_EQ(1, BLI_findindex(&lb, link2));
+ EXPECT_EQ(BLI_findlink(&lb, 1), link2);
+ EXPECT_EQ(BLI_rfindlink(&lb, 0), link2);
+ EXPECT_EQ(BLI_findindex(&lb, link2), 1);
BLI_freelistN(&lb);
}
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index c80987c3586..d017ab18b4d 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -121,42 +121,42 @@ TEST(path_util, PathUtilFrame)
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 1);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("123", path);
}
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 12);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("000000000123", path);
}
{
char path[FILE_MAX] = "test_";
ret = BLI_path_frame(path, 123, 1);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_123", path);
}
{
char path[FILE_MAX] = "test_";
ret = BLI_path_frame(path, 1, 12);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_000000000001", path);
}
{
char path[FILE_MAX] = "test_############";
ret = BLI_path_frame(path, 1, 0);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_000000000001", path);
}
{
char path[FILE_MAX] = "test_#_#_middle";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_#_123_middle", path);
}
@@ -164,14 +164,14 @@ TEST(path_util, PathUtilFrame)
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(0, ret);
+ EXPECT_EQ(ret, 0);
EXPECT_STREQ("", path);
}
{
char path[FILE_MAX] = "test_middle";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(0, ret);
+ EXPECT_EQ(ret, 0);
EXPECT_STREQ("test_middle", path);
}
}
diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
index a4ed70fbec9..5d112751fa0 100644
--- a/tests/gtests/blenlib/BLI_polyfill2d_test.cc
+++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
@@ -98,14 +98,14 @@ static void test_polyfill_topology(
}
}
}
- EXPECT_EQ(poly_tot + (poly_tot - 3), BLI_edgehash_size(edgehash));
+ EXPECT_EQ(BLI_edgehash_size(edgehash), poly_tot + (poly_tot - 3));
for (i = 0; i < poly_tot; i++) {
const unsigned int v1 = i;
const unsigned int v2 = (i + 1) % poly_tot;
void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
- EXPECT_EQ(1, (void *)p != NULL);
- EXPECT_EQ(1, (intptr_t)*p);
+ EXPECT_EQ((void *)p != NULL, 1);
+ EXPECT_EQ((intptr_t)*p, 1);
}
for (ehi = BLI_edgehashIterator_new(edgehash), i = 0;
@@ -113,7 +113,7 @@ static void test_polyfill_topology(
BLI_edgehashIterator_step(ehi), i++)
{
void **p = BLI_edgehashIterator_getValue_p(ehi);
- EXPECT_EQ(true, ELEM((intptr_t)*p, 1, 2));
+ EXPECT_TRUE(ELEM((intptr_t)*p, 1, 2));
}
BLI_edgehashIterator_free(ehi);
@@ -135,7 +135,7 @@ static void test_polyfill_winding(
count[winding_test < 0.0f] += 1;
}
}
- EXPECT_EQ(true, ELEM(0, count[0], count[1]));
+ EXPECT_TRUE(ELEM(0, count[0], count[1]));
}
/**
diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc
index 4c0b95f4b6b..18188937355 100644
--- a/tests/gtests/blenlib/BLI_stack_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_test.cc
@@ -24,7 +24,7 @@ TEST(stack, Empty)
BLI_Stack *stack;
stack = BLI_stack_new(sizeof(int), __func__);
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
EXPECT_EQ(BLI_stack_count(stack), 0);
BLI_stack_free(stack);
}
@@ -37,11 +37,11 @@ TEST(stack, One)
stack = BLI_stack_new(sizeof(in), __func__);
BLI_stack_push(stack, (void *)&in);
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
EXPECT_EQ(BLI_stack_count(stack), 1);
BLI_stack_pop(stack, (void *)&out);
- EXPECT_EQ(in, out);
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_EQ(out, in);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
EXPECT_EQ(BLI_stack_count(stack), 0);
BLI_stack_free(stack);
}
@@ -59,12 +59,12 @@ TEST(stack, Range)
}
for (in = tot - 1; in >= 0; in--) {
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
BLI_stack_pop(stack, (void *)&out);
- EXPECT_EQ(in, out);
+ EXPECT_EQ(out, in);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
BLI_stack_free(stack);
}
@@ -86,12 +86,12 @@ TEST(stack, String)
}
for (i = tot - 1; i >= 0; i--) {
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
*((int *)in) = i;
BLI_stack_pop(stack, (void *)&out);
EXPECT_STREQ(in, out);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
BLI_stack_free(stack);
}
@@ -115,7 +115,7 @@ TEST(stack, Peek)
EXPECT_EQ(*ret, in[i % ARRAY_SIZE(in)]);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
BLI_stack_free(stack);
}
@@ -140,7 +140,7 @@ TEST(stack, Clear)
}
BLI_stack_clear(stack);
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
/* and again, this time check its valid */
for (in = 0; in < tot; in++) {
@@ -148,12 +148,12 @@ TEST(stack, Clear)
}
for (in = tot - 1; in >= 0; in--) {
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
BLI_stack_pop(stack, (void *)&out);
- EXPECT_EQ(in, out);
+ EXPECT_EQ(out, in);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
/* without this, we wont test case when mixed free/used */
tot /= 2;
@@ -204,10 +204,10 @@ TEST(stack, Reuse)
while (!BLI_stack_is_empty(stack)) {
i--;
BLI_stack_pop(stack, (void *)&sizes_test[i]);
- EXPECT_EQ(sizes[i], sizes_test[i]);
+ EXPECT_EQ(sizes_test[i], sizes[i]);
EXPECT_GT(i, -1);
}
- EXPECT_EQ(i, 0);
+ EXPECT_EQ(0, i);
EXPECT_EQ(memcmp(sizes, sizes_test, sizeof(sizes) - sizeof(int)), 0);
diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc
index 08f2a745bdb..f6f7e17c8ca 100644
--- a/tests/gtests/blenlib/BLI_string_test.cc
+++ b/tests/gtests/blenlib/BLI_string_test.cc
@@ -44,7 +44,7 @@ TEST(string, StrPartition)
/* "mat.e-r_ial" -> "mat", '.', "e-r_ial", 3 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(3, pre_ln);
+ EXPECT_EQ(pre_ln, 3);
EXPECT_EQ(&str[3], sep);
EXPECT_STREQ("e-r_ial", suf);
}
@@ -55,7 +55,7 @@ TEST(string, StrPartition)
/* ".mate-rial--" -> "", '.', "mate-rial--", 0 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ("mate-rial--", suf);
}
@@ -65,7 +65,7 @@ TEST(string, StrPartition)
/* ".__.--_" -> "", '.', "__.--_", 0 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ("__.--_", suf);
}
@@ -75,9 +75,9 @@ TEST(string, StrPartition)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -85,9 +85,9 @@ TEST(string, StrPartition)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -103,7 +103,7 @@ TEST(string, StrRPartition)
/* "mat.e-r_ial" -> "mat.e-r", '_', "ial", 7 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(7, pre_ln);
+ EXPECT_EQ(pre_ln, 7);
EXPECT_EQ(&str[7], sep);
EXPECT_STREQ("ial", suf);
}
@@ -114,7 +114,7 @@ TEST(string, StrRPartition)
/* ".mate-rial--" -> ".mate-rial-", '-', "", 11 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(11, pre_ln);
+ EXPECT_EQ(pre_ln, 11);
EXPECT_EQ(&str[11], sep);
EXPECT_STREQ("", suf);
}
@@ -124,7 +124,7 @@ TEST(string, StrRPartition)
/* ".__.--_" -> ".__.--", '_', "", 6 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(6, pre_ln);
+ EXPECT_EQ(pre_ln, 6);
EXPECT_EQ(&str[6], sep);
EXPECT_STREQ("", suf);
}
@@ -134,9 +134,9 @@ TEST(string, StrRPartition)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -144,9 +144,9 @@ TEST(string, StrRPartition)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -164,7 +164,7 @@ TEST(string, StrPartitionEx)
/* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */
pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true);
- EXPECT_EQ(5, pre_ln);
+ EXPECT_EQ(pre_ln, 5);
EXPECT_EQ(&str[5], sep);
EXPECT_STREQ("r_ia.l", suf);
}
@@ -175,9 +175,9 @@ TEST(string, StrPartitionEx)
/* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */
pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true);
- EXPECT_EQ(4, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 4);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -193,7 +193,7 @@ TEST(string, StrPartitionUtf8)
/* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(2, pre_ln);
+ EXPECT_EQ(pre_ln, 2);
EXPECT_EQ(&str[2], sep);
EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
}
@@ -204,7 +204,7 @@ TEST(string, StrPartitionUtf8)
/* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "", '\xe2\x98\xaf', "mate-rial-\xc3\xb1", 0 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ("mate-rial-\xc3\xb1", suf);
}
@@ -214,7 +214,7 @@ TEST(string, StrPartitionUtf8)
/* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "", '\xe2\x98\xaf', ".\xc3\xb1_.--\xc3\xb1", 0 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ(".\xc3\xb1_.--\xc3\xb1", suf);
}
@@ -224,9 +224,9 @@ TEST(string, StrPartitionUtf8)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -234,9 +234,9 @@ TEST(string, StrPartitionUtf8)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -252,7 +252,7 @@ TEST(string, StrRPartitionUtf8)
/* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "mat\xc3\xb1te-r", '\xe2\x98\xaf', "ial", 8 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
+ EXPECT_EQ(pre_ln, 8);
EXPECT_EQ(&str[8], sep);
EXPECT_STREQ("ial", suf);
}
@@ -263,7 +263,7 @@ TEST(string, StrRPartitionUtf8)
/* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "\xe2\x98\xafmate-rial-", '\xc3\xb1', "", 13 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(13, pre_ln);
+ EXPECT_EQ(pre_ln, 13);
EXPECT_EQ(&str[13], sep);
EXPECT_STREQ("", suf);
}
@@ -273,7 +273,7 @@ TEST(string, StrRPartitionUtf8)
/* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "\xe2\x98\xaf.\xc3\xb1_.--", '\xc3\xb1', "", 10 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(10, pre_ln);
+ EXPECT_EQ(pre_ln, 10);
EXPECT_EQ(&str[10], sep);
EXPECT_STREQ("", suf);
}
@@ -283,9 +283,9 @@ TEST(string, StrRPartitionUtf8)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -293,9 +293,9 @@ TEST(string, StrRPartitionUtf8)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -313,7 +313,7 @@ TEST(string, StrPartitionExUtf8)
/* "ma\xc3\xb1te-r\xe2\x98\xafial" over "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true);
- EXPECT_EQ(2, pre_ln);
+ EXPECT_EQ(pre_ln, 2);
EXPECT_EQ(&str[2], sep);
EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
}
@@ -324,9 +324,9 @@ TEST(string, StrPartitionExUtf8)
/* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */
pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true);
- EXPECT_EQ(4, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 4);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -373,7 +373,7 @@ TEST(string, StrFormatIntGrouped)
const int word_cmp_size = ARRAY_SIZE(word_cmp); \
const int word_num = BLI_string_find_split_words( \
word_str_src, word_str_src_len, ' ', word_info, word_cmp_size_input); \
- EXPECT_EQ(word_num, word_cmp_size - 1); \
+ EXPECT_EQ(word_cmp_size - 1, word_num); \
EXPECT_EQ_ARRAY_ND<const int[2]>(word_cmp, word_info, word_cmp_size, 2); \
} ((void)0)
@@ -449,20 +449,20 @@ TEST(string, StringStrncasestr)
const char *res;
res = BLI_strncasestr(str_test0, "", 0);
- EXPECT_EQ(str_test0, res);
+ EXPECT_EQ(res, str_test0);
res = BLI_strncasestr(str_test0, " ", 1);
- EXPECT_EQ(str_test0 + 6, res);
+ EXPECT_EQ(res, str_test0 + 6);
res = BLI_strncasestr(str_test0, "her", 3);
- EXPECT_EQ(str_test0 + 7, res);
+ EXPECT_EQ(res, str_test0 + 7);
res = BLI_strncasestr(str_test0, "ARCh", 4);
- EXPECT_EQ(str_test0 + 2, res);
+ EXPECT_EQ(res, str_test0 + 2);
res = BLI_strncasestr(str_test0, "earcq", 4);
- EXPECT_EQ(str_test0 + 1, res);
+ EXPECT_EQ(res, str_test0 + 1);
res = BLI_strncasestr(str_test0, "not there", 9);
- EXPECT_EQ(NULL, res);
+ EXPECT_EQ(res, (void*)NULL);
}
diff --git a/tests/gtests/blenlib/BLI_string_utf8_test.cc b/tests/gtests/blenlib/BLI_string_utf8_test.cc
index c0beb92eeec..95d73b4242f 100644
--- a/tests/gtests/blenlib/BLI_string_utf8_test.cc
+++ b/tests/gtests/blenlib/BLI_string_utf8_test.cc
@@ -298,7 +298,7 @@ TEST(string, Utf8InvalidBytes)
const int num_errors_found = BLI_utf8_invalid_strip(buff, sizeof(buff) - 1);
printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", num_errors, num_errors_found, tst, buff);
- EXPECT_EQ(num_errors, num_errors_found);
+ EXPECT_EQ(num_errors_found, num_errors);
EXPECT_STREQ(buff, tst_stripped);
}
}
diff --git a/tests/gtests/bmesh/bmesh_core_test.cc b/tests/gtests/bmesh/bmesh_core_test.cc
index f386abc0b2b..b2cb1a4e8a3 100644
--- a/tests/gtests/bmesh/bmesh_core_test.cc
+++ b/tests/gtests/bmesh/bmesh_core_test.cc
@@ -12,18 +12,18 @@ TEST(bmesh_core, BMVertCreate) {
BMeshCreateParams bm_params;
bm_params.use_toolflags = true;
bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_params);
- EXPECT_EQ(0, bm->totvert);
+ EXPECT_EQ(bm->totvert, 0);
/* make a custom layer so we can see if it is copied properly */
BM_data_layer_add(bm, &bm->vdata, CD_PROP_FLT);
bv1 = BM_vert_create(bm, co1, NULL, BM_CREATE_NOP);
ASSERT_TRUE(bv1 != NULL);
- EXPECT_EQ(1.0f, bv1->co[0]);
- EXPECT_EQ(2.0f, bv1->co[1]);
- EXPECT_EQ(0.0f, bv1->co[2]);
+ EXPECT_EQ(bv1->co[0], 1.0f);
+ EXPECT_EQ(bv1->co[1], 2.0f);
+ EXPECT_EQ(bv1->co[2], 0.0f);
EXPECT_TRUE(is_zero_v3(bv1->no));
- EXPECT_EQ((char)BM_VERT, bv1->head.htype);
- EXPECT_EQ(0, bv1->head.hflag);
- EXPECT_EQ(0, bv1->head.api_flag);
+ EXPECT_EQ(bv1->head.htype, (char)BM_VERT);
+ EXPECT_EQ(bv1->head.hflag, 0);
+ EXPECT_EQ(bv1->head.api_flag, 0);
bv2 = BM_vert_create(bm, NULL, NULL, BM_CREATE_NOP);
ASSERT_TRUE(bv2 != NULL);
EXPECT_TRUE(is_zero_v3(bv2->co));
@@ -33,7 +33,7 @@ TEST(bmesh_core, BMVertCreate) {
bv3 = BM_vert_create(bm, co1, bv2, BM_CREATE_NOP);
ASSERT_TRUE(bv3 != NULL);
EXPECT_FALSE(BM_elem_flag_test((BMElem *)bv3, BM_ELEM_SELECT));
- EXPECT_EQ(1.5f, BM_elem_float_data_get(&bm->vdata, bv3, CD_PROP_FLT));
- EXPECT_EQ(3, BM_mesh_elem_count(bm, BM_VERT));
+ EXPECT_EQ(BM_elem_float_data_get(&bm->vdata, bv3, CD_PROP_FLT), 1.5f);
+ EXPECT_EQ(BM_mesh_elem_count(bm, BM_VERT), 3);
BM_mesh_free(bm);
}
diff --git a/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc b/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc
index 345c3824b63..01ff38f0528 100644
--- a/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc
+++ b/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc
@@ -8,7 +8,7 @@ extern "C" {
#include "MEM_guardedalloc.h"
-#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ(0, (size_t)ptr % align)
+#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ((size_t)ptr % align, 0)
namespace {
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 4b5666e9b5a..4e0283adf88 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -425,3 +425,10 @@ if(WITH_CYCLES)
MESSAGE(STATUS "Disabling Cycles tests because tests folder does not exist")
endif()
endif()
+
+# ------------------------------------------------------------------------------
+# LAYER SYSTEM TESTS
+add_test(render_layer ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_render_layer.py --
+ --testdir="${TEST_SRC_DIR}/layers"
+)
diff --git a/tests/python/bl_render_layer.py b/tests/python/bl_render_layer.py
new file mode 100644
index 00000000000..e0b1711c9dc
--- /dev/null
+++ b/tests/python/bl_render_layer.py
@@ -0,0 +1,1040 @@
+# Apache License, Version 2.0
+
+# ./blender.bin --background -noaudio --python tests/python/bl_render_layer.py -- --testdir="/data/lib/tests/"
+import unittest
+
+
+# ############################################################
+# Layer Collection Crawler
+# ############################################################
+
+def listbase_iter(data, struct, listbase):
+ element = data.get_pointer((struct, listbase, b'first'))
+ while element is not None:
+ yield element
+ element = element.get_pointer(b'next')
+
+
+def linkdata_iter(collection, data):
+ element = collection.get_pointer((data, b'first'))
+ while element is not None:
+ yield element
+ element = element.get_pointer(b'next')
+
+
+def get_layer_collection(layer_collection):
+ data = {}
+ flag = layer_collection.get(b'flag')
+
+ data['is_visible'] = (flag & (1 << 0)) != 0;
+ data['is_selectable'] = (flag & (1 << 1)) != 0;
+ data['is_folded'] = (flag & (1 << 2)) != 0;
+
+ scene_collection = layer_collection.get_pointer(b'scene_collection')
+ if scene_collection is None:
+ name = 'Fail!'
+ else:
+ name = scene_collection.get(b'name')
+ data['name'] = name
+
+ objects = []
+ for link in linkdata_iter(layer_collection, b'object_bases'):
+ ob_base = link.get_pointer(b'data')
+ ob = ob_base.get_pointer(b'object')
+ objects.append(ob.get((b'id', b'name'))[2:])
+ data['objects'] = objects
+
+ collections = {}
+ for nested_layer_collection in linkdata_iter(layer_collection, b'layer_collections'):
+ subname, subdata = get_layer_collection(nested_layer_collection)
+ collections[subname] = subdata
+ data['collections'] = collections
+
+ return name, data
+
+
+def get_layer(layer):
+ data = {}
+ name = layer.get(b'name')
+
+ data['name'] = name
+ data['active_object'] = layer.get((b'basact', b'object', b'id', b'name'))[2:]
+ data['engine'] = layer.get(b'engine')
+
+ objects = []
+ for link in linkdata_iter(layer, b'object_bases'):
+ ob = link.get_pointer(b'object')
+ objects.append(ob.get((b'id', b'name'))[2:])
+ data['objects'] = objects
+
+ collections = {}
+ for layer_collection in linkdata_iter(layer, b'layer_collections'):
+ subname, subdata = get_layer_collection(layer_collection)
+ collections[subname] = subdata
+ data['collections'] = collections
+
+ return name, data
+
+
+def get_layers(scene):
+ """Return all the render layers and their data"""
+ layers = {}
+ for layer in linkdata_iter(scene, b'render_layers'):
+ name, data = get_layer(layer)
+ layers[name] = data
+ return layers
+
+
+def get_scene_collection_objects(collection, listbase):
+ objects = []
+ for link in linkdata_iter(collection, listbase):
+ ob = link.get_pointer(b'data')
+ if ob is None:
+ name = 'Fail!'
+ else:
+ name = ob.get((b'id', b'name'))[2:]
+ objects.append(name)
+ return objects
+
+
+def get_scene_collection(collection):
+ """"""
+ data = {}
+ name = collection.get(b'name')
+
+ data['name'] = name
+ data['filter'] = collection.get(b'filter')
+
+ data['objects'] = get_scene_collection_objects(collection, b'objects')
+ data['filter_objects'] = get_scene_collection_objects(collection, b'filter_objects')
+
+ collections = {}
+ for nested_collection in linkdata_iter(collection, b'scene_collections'):
+ subname, subdata = get_scene_collection(nested_collection)
+ collections[subname] = subdata
+ data['collections'] = collections
+
+ return name, data
+
+
+def get_scene_collections(scene):
+ """Return all the scene collections ahd their data"""
+ master_collection = scene.get_pointer(b'collection')
+ return get_scene_collection(master_collection)
+
+
+def query_scene(filepath, name, callbacks):
+ """Return the equivalent to bpy.context.scene"""
+ import blendfile
+ with blendfile.open_blend(filepath) as blend:
+ scenes = [block for block in blend.blocks if block.code == b'SC']
+ for scene in scenes:
+ if scene.get((b'id', b'name'))[2:] == name:
+ output = []
+ for callback in callbacks:
+ output.append(callback(scene))
+ return output
+
+
+# ############################################################
+# Utils
+# ############################################################
+
+def import_blendfile():
+ import bpy
+ import os, sys
+ path = os.path.join(
+ bpy.utils.resource_path('LOCAL'),
+ 'scripts',
+ 'addons',
+ 'io_blend_utils',
+ 'blend',
+ )
+
+ if path not in sys.path:
+ sys.path.append(path)
+
+
+def dump(data):
+ import json
+ return json.dumps(
+ data,
+ sort_keys=True,
+ indent=4,
+ separators=(',', ': '),
+ )
+
+
+# ############################################################
+# Tests
+# ############################################################
+
+PDB = False
+DUMP_DIFF = True
+
+def compare_files(file_a, file_b):
+ import filecmp
+
+ if not filecmp.cmp(
+ file_a,
+ file_b):
+
+ if DUMP_DIFF:
+ import subprocess
+ subprocess.call(["diff", "-u", file_a, file_b])
+
+ if PDB:
+ import pdb
+ print("Files differ:", file_a, file_b)
+ pdb.set_trace()
+
+ return False
+
+ return True
+
+
+class UnitsTesting(unittest.TestCase):
+ _test_simple = False
+
+ @classmethod
+ def setUpClass(cls):
+ """Runs once"""
+ cls.pretest_import_blendfile()
+ cls.pretest_parsing()
+
+ @classmethod
+ def setUp(cls):
+ """Runs once per test"""
+ import bpy
+ bpy.ops.wm.read_factory_settings()
+
+ def path_exists(self, filepath):
+ import os
+ self.assertTrue(
+ os.path.exists(filepath),
+ "Test file \"{0}\" not found".format(filepath))
+
+ @classmethod
+ def get_root(cls):
+ """
+ return the folder with the test files
+ """
+ arguments = {}
+ for argument in extra_arguments:
+ name, value = argument.split('=')
+ cls.assertTrue(name and name.startswith("--"), "Invalid argument \"{0}\"".format(argument))
+ cls.assertTrue(value, "Invalid argument \"{0}\"".format(argument))
+ arguments[name[2:]] = value.strip('"')
+
+ return arguments.get('testdir')
+
+ @classmethod
+ def pretest_parsing(cls):
+ """
+ Test if the arguments are properly set, and store ROOT
+ name has extra _ because we need this test to run first
+ """
+ root = cls.get_root()
+ cls.assertTrue(root, "Testdir not set")
+
+ @staticmethod
+ def pretest_import_blendfile():
+ """
+ Make sure blendfile imports with no problems
+ name has extra _ because we need this test to run first
+ """
+ import_blendfile()
+ import blendfile
+
+ def do_scene_write_read(self, filepath_layers, filepath_layers_json, data_callbacks, do_read):
+ """
+ See if write/read is working for scene collections and layers
+ """
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ with tempfile.TemporaryDirectory() as dirpath:
+ (self.path_exists(f) for f in (filepath_layers, filepath_layers_json))
+
+ filepath_doversion = os.path.join(dirpath, 'doversion.blend')
+ filepath_saved = os.path.join(dirpath, 'doversion_saved.blend')
+ filepath_read_json = os.path.join(dirpath, "read.json")
+
+ # doversion + write test
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_doversion)
+
+ datas = query_scene(filepath_doversion, 'Main', data_callbacks)
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_doversion_json = os.path.join(dirpath, "doversion.json")
+ with open(filepath_doversion_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_doversion_json,
+ filepath_layers_json,
+ ),
+ "Run: test_scene_write_layers")
+
+ if do_read:
+ # read test, simply open and save the file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_doversion)
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved)
+
+ datas = query_scene(filepath_saved, 'Main', data_callbacks)
+ self.assertTrue(datas, "Data is not valid")
+
+ with open(filepath_read_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_read_json,
+ filepath_layers_json,
+ ),
+ "Scene dump files differ")
+
+ def test_scene_write_collections(self):
+ """
+ See if the doversion and writing are working for scene collections
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers_simple.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections,),
+ False)
+
+ def test_scene_write_layers(self):
+ """
+ See if the doversion and writing are working for collections and layers
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections, get_layers),
+ False)
+
+ def test_scene_read_collections(self):
+ """
+ See if read is working for scene collections
+ (run `test_scene_write_colections` first)
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers_simple.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections,),
+ True)
+
+ def test_scene_read_layers(self):
+ """
+ See if read is working for scene layers
+ (run `test_scene_write_layers` first)
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections, get_layers),
+ True)
+
+ def do_scene_copy(self, filepath_json_reference, copy_mode, data_callbacks):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ (self.path_exists(f) for f in (
+ filepath_layers,
+ filepath_json_reference,
+ ))
+
+ filepath_saved = os.path.join(dirpath, '{0}.blend'.format(copy_mode))
+ filepath_json = os.path.join(dirpath, "{0}.json".format(copy_mode))
+
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ bpy.ops.scene.new(type=copy_mode)
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved)
+
+ datas = query_scene(filepath_saved, 'Main.001', data_callbacks)
+ self.assertTrue(datas, "Data is not valid")
+
+ with open(filepath_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_json,
+ filepath_json_reference,
+ ),
+ "Scene copy \"{0}\" test failed".format(copy_mode.title()))
+
+ def test_scene_collections_copy_full(self):
+ """
+ See if scene copying 'FULL_COPY' is working for scene collections
+ """
+ import os
+ ROOT = self.get_root()
+
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full_simple.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'FULL_COPY',
+ (get_scene_collections,))
+
+ def test_scene_collections_link(self):
+ """
+ See if scene copying 'LINK_OBJECTS' is working for scene collections
+ """
+ import os
+ ROOT = self.get_root()
+
+ # note: nothing should change, so using `layers_simple.json`
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_simple.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'LINK_OBJECTS',
+ (get_scene_collections,))
+
+ def test_scene_layers_copy(self):
+ """
+ See if scene copying 'FULL_COPY' is working for scene layers
+ """
+ import os
+ ROOT = self.get_root()
+
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'FULL_COPY',
+ (get_scene_collections, get_layers))
+
+ def test_scene_layers_link(self):
+ """
+ See if scene copying 'FULL_COPY' is working for scene layers
+ """
+ import os
+ ROOT = self.get_root()
+
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_link.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'LINK_OBJECTS',
+ (get_scene_collections, get_layers))
+
+ def do_syncing(self, filepath_json, unlink_mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+ three_d = bpy.data.objects.get('T.3d')
+
+ scene = bpy.context.scene
+
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = scene.master_collection.collections['1'].collections.new('scorpion')
+
+ # test linking sync
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+
+ # test unlinking sync
+ if unlink_mode in {'OBJECT', 'COLLECTION'}:
+ scorpion.objects.link(three_d)
+ scorpion.objects.unlink(three_d)
+
+ if unlink_mode == 'COLLECTION':
+ scorpion.objects.link(three_d)
+ scene.master_collection.collections['1'].collections.remove(subzero)
+ scene.master_collection.collections['1'].collections.remove(scorpion)
+
+ # save file
+ filepath_nested = os.path.join(dirpath, 'nested.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested)
+
+ # get the generated json
+ datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_nested_json = os.path.join(dirpath, "nested.json")
+ with open(filepath_nested_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_nested_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def test_syncing_link(self):
+ """
+ See if scene collections and layer collections are in sync
+ when we create new subcollections and link new objects
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_nested.json')
+ self.do_syncing(filepath_json, 'NONE')
+
+ def test_syncing_unlink_object(self):
+ """
+ See if scene collections and layer collections are in sync
+ when we create new subcollections, link new objects and unlink
+ some.
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_nested.json')
+ self.do_syncing(filepath_json, 'OBJECT')
+
+ def test_syncing_unlink_collection(self):
+ """
+ See if scene collections and layer collections are in sync
+ when we create new subcollections, link new objects and unlink full collections
+ some.
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers.json')
+ self.do_syncing(filepath_json, 'COLLECTION')
+
+ def do_layer_linking(self, filepath_json, link_mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+
+ # test linking sync
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+
+ # test unlinking sync
+ layer = scene.render_layers.new('Fresh new Layer')
+
+ if link_mode in {'COLLECTION_LINK', 'COLLECTION_UNLINK'}:
+ layer.collections.link(subzero)
+
+ if link_mode == 'COLLECTION_UNLINK':
+ initial_collection = layer.collections['Master Collection']
+ layer.collections.unlink(initial_collection)
+
+ # save file
+ filepath_nested = os.path.join(dirpath, 'nested.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested)
+
+ # get the generated json
+ datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_nested_json = os.path.join(dirpath, "nested.json")
+ with open(filepath_nested_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_nested_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def test_syncing_layer_new(self):
+ """
+ See if the creation of new layers is going well
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_new_layer.json')
+ self.do_layer_linking(filepath_json, 'LAYER_NEW')
+
+ def test_syncing_layer_collection_link(self):
+ """
+ See if the creation of new layers is going well
+ And linking a new scene collection in the layer works
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_layer_collection_link.json')
+ self.do_layer_linking(filepath_json, 'COLLECTION_LINK')
+
+ def test_syncing_layer_collection_unlink(self):
+ """
+ See if the creation of new layers is going well
+ And unlinking the origin scene collection works
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_layer_collection_unlink.json')
+ self.do_layer_linking(filepath_json, 'COLLECTION_UNLINK')
+
+ def test_active_collection(self):
+ """
+ See if active collection index is working
+ layer.collections.active_index works recursively
+ """
+ import bpy
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.link(subzero)
+
+ lookup = [
+ 'Master Collection',
+ '1',
+ 'sub-zero',
+ 'scorpion',
+ '2',
+ '3',
+ '4',
+ '5',
+ 'sub-zero',
+ 'scorpion']
+
+ for i, name in enumerate(lookup):
+ layer.collections.active_index = i
+ self.assertEqual(name, layer.collections.active.name,
+ "Collection index mismatch: [{0}] : {1} != {2}".format(
+ i, name, layer.collections.active.name))
+
+ def do_object_delete(self, del_mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_reference_json = os.path.join(ROOT, 'layers_object_delete.json')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_d = bpy.data.objects.get('T.3d')
+
+ scene = bpy.context.scene
+
+ # mangle the file a bit with some objects linked across collections
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_d)
+ scorpion.objects.link(three_b)
+ scorpion.objects.link(three_d)
+
+ # object to delete
+ ob = three_d
+
+ # delete object
+ if del_mode == 'DATA':
+ bpy.data.objects.remove(ob, do_unlink=True)
+
+ elif del_mode == 'OPERATOR':
+ bpy.ops.object.select_all(action='DESELECT')
+ ob.select_set(action='SELECT')
+ bpy.ops.object.delete()
+
+ # save file
+ filepath_generated = os.path.join(dirpath, 'generated.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_generated)
+
+ # get the generated json
+ datas = query_scene(filepath_generated, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_generated_json = os.path.join(dirpath, "generated.json")
+ with open(filepath_generated_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_generated_json,
+ filepath_reference_json,
+ ),
+ "Scene dump files differ")
+
+ def test_object_delete_data(self):
+ """
+ See if objects are removed correctly from all related collections
+ bpy.data.objects.remove()
+ """
+ self.do_object_delete('DATA')
+
+ def test_object_delete_operator(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.object.del()
+ """
+ self.do_object_delete('OPERATOR')
+
+ def do_link(self, master_collection):
+ import bpy
+ self.assertEqual(master_collection.name, "Master Collection")
+ self.assertEqual(master_collection, bpy.context.scene.master_collection)
+ master_collection.objects.link(bpy.data.objects.new('object', None))
+
+ def test_link_scene(self):
+ """
+ See if we can link objects
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+ self.do_link(master_collection)
+
+ def test_link_context(self):
+ """
+ See if we can link objects via bpy.context.scene_collection
+ """
+ import bpy
+ bpy.context.scene.render_layers.active_index = len(bpy.context.scene.render_layers) - 1
+ master_collection = bpy.context.scene_collection
+ self.do_link(master_collection)
+
+ def test_operator_context(self):
+ """
+ See if render layer context is properly set/get with operators overrides
+ when we set render_layer in context, the collection should change as well
+ """
+ import bpy
+ import os
+
+ class SampleOperator(bpy.types.Operator):
+ bl_idname = "testing.sample"
+ bl_label = "Sample Operator"
+
+ render_layer = bpy.props.StringProperty(
+ default="Not Set",
+ options={'SKIP_SAVE'},
+ )
+
+ scene_collection = bpy.props.StringProperty(
+ default="",
+ options={'SKIP_SAVE'},
+ )
+
+ use_verbose = bpy.props.BoolProperty(
+ default=False,
+ options={'SKIP_SAVE'},
+ )
+
+ def execute(self, context):
+ render_layer = context.render_layer
+ ret = {'FINISHED'}
+
+ # this is simply playing safe
+ if render_layer.name != self.render_layer:
+ if self.use_verbose:
+ print('ERROR: Render Layer mismatch: "{0}" != "{1}"'.format(
+ render_layer.name, self.render_layer))
+ ret = {'CANCELLED'}
+
+ scene_collection_name = None
+ if self.scene_collection:
+ scene_collection_name = self.scene_collection
+ else:
+ scene_collection_name = render_layer.collections.active.name
+
+ # while this is the real test
+ if context.scene_collection.name != scene_collection_name:
+ if self.use_verbose:
+ print('ERROR: Scene Collection mismatch: "{0}" != "{1}"'.format(
+ context.scene_collection.name, scene_collection_name))
+ ret = {'CANCELLED'}
+ return ret
+
+ bpy.utils.register_class(SampleOperator)
+
+ # open sample file
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+
+ # change the file
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.unlink(layer.collections.active)
+ layer.collections.link(subzero)
+ layer.collections.active_index = 3
+ self.assertEqual(layer.collections.active.name, 'scorpion')
+
+ scene = bpy.context.scene
+ scene.render_layers.active_index = len(scene.render_layers) - 2
+ self.assertEqual(scene.render_layers.active.name, "Render Layer")
+
+ # old layer
+ self.assertEqual(bpy.ops.testing.sample(render_layer='Render Layer', use_verbose=True), {'FINISHED'})
+
+ # expected to fail
+ self.assertTrue(bpy.ops.testing.sample(render_layer=layer.name), {'CANCELLED'})
+
+ # set render layer and scene collection
+ override = bpy.context.copy()
+ override["render_layer"] = layer
+ override["scene_collection"] = subzero
+ self.assertEqual(bpy.ops.testing.sample(override,
+ render_layer=layer.name,
+ scene_collection=subzero.name, # 'sub-zero'
+ use_verbose=True), {'FINISHED'})
+
+ # set only render layer
+ override = bpy.context.copy()
+ override["render_layer"] = layer
+
+ self.assertEqual(bpy.ops.testing.sample(override,
+ render_layer=layer.name,
+ scene_collection=layer.collections.active.name, # 'scorpion'
+ use_verbose=True), {'FINISHED'})
+
+ def do_object_add(self, filepath_json, add_mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.link(subzero)
+
+ # change active collection
+ layer.collections.active_index = 3
+ self.assertEqual(layer.collections.active.name, 'scorpion', "Run: test_syncing_object_add")
+
+ # change active layer
+ override = bpy.context.copy()
+ override["render_layer"] = layer
+ override["scene_collection"] = layer.collections.active.collection
+
+ # add new objects
+ if add_mode == 'EMPTY':
+ bpy.ops.object.add(override) # 'Empty'
+
+ elif add_mode == 'CYLINDER':
+ bpy.ops.mesh.primitive_cylinder_add(override) # 'Cylinder'
+
+ elif add_mode == 'TORUS':
+ bpy.ops.mesh.primitive_torus_add(override) # 'Torus'
+
+ # save file
+ filepath_objects = os.path.join(dirpath, 'objects.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects)
+
+ # get the generated json
+ datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_objects_json = os.path.join(dirpath, "objects.json")
+ with open(filepath_objects_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_objects_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def test_syncing_object_add_empty(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.object.add()
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_object_add_empty.json')
+ self.do_object_add(filepath_json, 'EMPTY')
+
+ def test_syncing_object_add_cylinder(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.mesh.primitive_cylinder_add()
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_object_add_cylinder.json')
+ self.do_object_add(filepath_json, 'CYLINDER')
+
+ def test_syncing_object_add_torus(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.mesh.primitive_torus_add()
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_object_add_torus.json')
+ self.do_object_add(filepath_json, 'TORUS')
+
+ def do_copy_object(self, mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_json = os.path.join(ROOT, 'layers_object_copy_duplicate.json')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.link(subzero)
+
+ scene.render_layers.active_index = len(scene.render_layers) - 1
+
+ if mode == 'DUPLICATE':
+ # assuming the latest layer is the active layer
+ bpy.ops.object.select_all(action='DESELECT')
+ three_c.select_set(action='SELECT')
+ bpy.ops.object.duplicate()
+
+ elif mode == 'NAMED':
+ bpy.ops.object.add_named(name=three_c.name)
+
+ # save file
+ filepath_objects = os.path.join(dirpath, 'objects.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects)
+
+ # get the generated json
+ datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_objects_json = os.path.join(dirpath, "objects.json")
+ with open(filepath_objects_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_objects_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def test_copy_object(self):
+ """
+ OBJECT_OT_duplicate
+ """
+ self.do_copy_object('DUPLICATE')
+
+ def test_copy_object_named(self):
+ """
+ OBJECT_OT_add_named
+ """
+ self.do_copy_object('NAMED')
+
+
+# ############################################################
+# Main
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ global extra_arguments
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+ unittest.main()
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
index ae8848570f0..64a71da301a 100755
--- a/tests/python/cycles_render_tests.py
+++ b/tests/python/cycles_render_tests.py
@@ -52,6 +52,7 @@ def render_file(filepath):
"--background",
"-noaudio",
"--factory-startup",
+ "--enable-autoexec",
filepath,
"-E", "CYCLES",
# Run with OSL enabled